dbrw.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  begin       : Tue Sep 09 2003
00003  copyright   : (C) 2003-2010 by Martin Preuss
00004  email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *                                                                         *
00008  *   This library is free software; you can redistribute it and/or         *
00009  *   modify it under the terms of the GNU Lesser General Public            *
00010  *   License as published by the Free Software Foundation; either          *
00011  *   version 2.1 of the License, or (at your option) any later version.    *
00012  *                                                                         *
00013  *   This library is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00016  *   Lesser General Public License for more details.                       *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU Lesser General Public      *
00019  *   License along with this library; if not, write to the Free Software   *
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00021  *   MA  02111-1307  USA                                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 
00026 /* This file is included from db.c */
00027 
00028 
00029 
00030 int GWEN_DB_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
00031   while(*src) {
00032     unsigned char x;
00033 
00034     x=(unsigned char)*src;
00035     if (!(
00036           (x>='A' && x<='Z') ||
00037           (x>='a' && x<='z') ||
00038           (x>='0' && x<='9') ||
00039           x=='%' ||
00040           x=='.' ||
00041           x==',' ||
00042           x=='.' ||
00043           x=='_' ||
00044           x=='-' ||
00045           x=='*' ||
00046           x=='?'
00047          )) {
00048       unsigned char c;
00049 
00050       GWEN_Buffer_AppendByte(buf, '&');
00051       c=(((unsigned char)(*src))>>4)&0xf;
00052       if (c>9)
00053         c+=7;
00054       c+='0';
00055       GWEN_Buffer_AppendByte(buf, c);
00056       c=((unsigned char)(*src))&0xf;
00057       if (c>9)
00058         c+=7;
00059       c+='0';
00060       GWEN_Buffer_AppendByte(buf, c);
00061     }
00062     else
00063       GWEN_Buffer_AppendByte(buf, *src);
00064 
00065     src++;
00066   } /* while */
00067 
00068   return 0;
00069 }
00070 
00071 
00072 
00073 int GWEN_DB_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
00074   while(*src) {
00075     int charHandled;
00076 
00077     charHandled=0;
00078     if (*src=='&') {
00079       if (strlen(src)>2) {
00080         unsigned char d1, d2;
00081         unsigned char c;
00082 
00083         if (isxdigit((int)src[1]) && isxdigit((int)src[2])) {
00084           /* skip '%' */
00085           src++;
00086           /* read first digit */
00087           d1=(unsigned char)(toupper(*src));
00088 
00089           /* get second digit */
00090           src++;
00091           d2=(unsigned char)(toupper(*src));
00092           /* compute character */
00093           d1-='0';
00094           if (d1>9)
00095             d1-=7;
00096           c=(d1<<4)&0xf0;
00097           d2-='0';
00098           if (d2>9)
00099             d2-=7;
00100           c+=(d2&0xf);
00101           /* store character */
00102           GWEN_Buffer_AppendByte(buf, (char)c);
00103           charHandled=1;
00104         }
00105       }
00106     }
00107     if (!charHandled)
00108       GWEN_Buffer_AppendByte(buf, *src);
00109     src++;
00110   } /* while */
00111 
00112   return 0;
00113 }
00114 
00115 
00116 
00117 
00118 
00119 
00120 int GWEN_DB_ReadFileAs(GWEN_DB_NODE *db,
00121                        const char *fname,
00122                        const char *type,
00123                        GWEN_DB_NODE *params,
00124                        uint32_t dbflags){
00125   GWEN_SYNCIO *sio;
00126   GWEN_DBIO *dbio;
00127   int rv;
00128 
00129   dbio=GWEN_DBIO_GetPlugin(type);
00130   if (!dbio) {
00131     DBG_ERROR(GWEN_LOGDOMAIN, "Plugin \"%s\" is not supported", type);
00132     return GWEN_ERROR_NOT_SUPPORTED;
00133   }
00134 
00135   sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting);
00136   GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
00137   rv=GWEN_SyncIo_Connect(sio);
00138   if (rv<0) {
00139     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00140     GWEN_SyncIo_free(sio);
00141     return rv;
00142   }
00143 
00144   rv=GWEN_DBIO_Import(dbio, sio, db, params, dbflags);
00145   if (rv<0) {
00146     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00147   }
00148   GWEN_SyncIo_Disconnect(sio);
00149   GWEN_SyncIo_free(sio);
00150 
00151   return rv;
00152 }
00153 
00154 
00155 
00156 int GWEN_DB_WriteFileAs(GWEN_DB_NODE *db,
00157                         const char *fname,
00158                         const char *type,
00159                         GWEN_DB_NODE *params,
00160                         uint32_t dbflags){
00161   int rv;
00162   GWEN_DBIO *dbio;
00163 
00164   dbio=GWEN_DBIO_GetPlugin(type);
00165   if (!dbio) {
00166     DBG_ERROR(GWEN_LOGDOMAIN, "Plugin \"%s\" is not supported", type);
00167     return GWEN_ERROR_NOT_SUPPORTED;
00168   }
00169 
00170   rv=GWEN_DBIO_ExportToFile(dbio, fname, db, params, dbflags);
00171   if (rv) {
00172     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00173     return rv;
00174   }
00175 
00176   return 0;
00177 }
00178 
00179 
00180 
00181 int GWEN_DB_WriteGroupToIoLayer(GWEN_DB_NODE *node,
00182                                 GWEN_FAST_BUFFER *fb,
00183                                 uint32_t dbflags,
00184                                 int insert) {
00185   GWEN_DB_NODE *n;
00186   GWEN_DB_NODE *cn;
00187   int i;
00188   int err;
00189   int lastWasVar;
00190 
00191   lastWasVar=0;
00192 
00193   n=GWEN_DB_Node_List_First(node->children);
00194   while(n) {
00195     if (!(n->nodeFlags & GWEN_DB_NODE_FLAGS_VOLATILE)) {
00196       DBG_VERBOUS(GWEN_LOGDOMAIN, "Writing node");
00197       switch(n->typ) {
00198       case GWEN_DB_NodeType_Group:
00199         if (dbflags & GWEN_DB_FLAGS_WRITE_SUBGROUPS) {
00200           GWEN_BUFFER *tbuf;
00201 
00202           if (dbflags & GWEN_DB_FLAGS_ADD_GROUP_NEWLINES) {
00203             if (lastWasVar) {
00204               /* only insert newline if the last one before this group was a
00205                * variable */
00206               GWEN_FASTBUFFER_WRITELINE(fb, err, "");
00207               if (err<0) {
00208                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00209                 return err;
00210               }
00211             }
00212           }
00213 
00214           /* indend */
00215           if (dbflags & GWEN_DB_FLAGS_INDEND) {
00216             for (i=0; i<insert; i++) {
00217               GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' ');
00218               if (err<0) {
00219                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00220                 return err;
00221               }
00222             } /* for */
00223           } /* if indend */
00224 
00225           tbuf=GWEN_Buffer_new(0, 128, 0, 1);
00226           err=GWEN_DB_EscapeToBufferTolerant(n->data.dataName, tbuf);
00227           if (err<0) {
00228             DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
00229             GWEN_Buffer_free(tbuf);
00230             return err;
00231           }
00232 
00233           GWEN_FASTBUFFER_WRITEFORCED(fb, err,
00234                                       GWEN_Buffer_GetStart(tbuf),
00235                                       GWEN_Buffer_GetUsedBytes(tbuf));
00236           GWEN_Buffer_free(tbuf);
00237           if (err<0) {
00238             DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
00239             return err;
00240           }
00241           GWEN_FASTBUFFER_WRITELINE(fb, err, " {");
00242           if (err<0) {
00243             DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00244             return err;
00245           }
00246           err=GWEN_DB_WriteGroupToIoLayer(n, fb, dbflags, insert+2);
00247           if (err<0)
00248             return err;
00249 
00250           /* indend */
00251           if (dbflags & GWEN_DB_FLAGS_INDEND) {
00252             for (i=0; i<insert; i++) {
00253               GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' ');
00254               if (err<0) {
00255                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00256                 return err;
00257               }
00258             } /* for */
00259           } /* if indend */
00260 
00261           if (dbflags & GWEN_DB_FLAGS_DETAILED_GROUPS) {
00262             GWEN_FASTBUFFER_WRITEFORCED(fb, err, "} #", -1);
00263             if (err<0) {
00264               DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00265               return err;
00266             }
00267             GWEN_FASTBUFFER_WRITELINE(fb, err, n->data.dataName);
00268             if (err<0) {
00269               DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00270               return err;
00271             }
00272           } /* if detailed groups */
00273           else {
00274             GWEN_FASTBUFFER_WRITELINE(fb, err, "}");
00275             if (err<0) {
00276               DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00277               return err;
00278             }
00279           }
00280           if (dbflags & GWEN_DB_FLAGS_ADD_GROUP_NEWLINES) {
00281             if (GWEN_DB_Node_List_Next(n)) {
00282               /* only insert newline if something
00283                * is following on the same level */
00284               GWEN_FASTBUFFER_WRITELINE(fb, err, "");
00285               if (err<0) {
00286                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00287                 return err;
00288               }
00289             }
00290           }
00291         }
00292         lastWasVar=0;
00293         break;
00294 
00295       case GWEN_DB_NodeType_Var:
00296         cn=GWEN_DB_Node_List_First(n->children);
00297         if (cn) {
00298           char *typname;
00299           int namewritten;
00300           int values;
00301 
00302           typname=0;
00303           namewritten=0;
00304           values=0;
00305           while(cn) {
00306             char numbuffer[32];
00307             char *binbuffer=NULL;
00308             unsigned int bbsize;
00309             const char *pvalue=NULL;
00310             GWEN_BUFFER *vbuf=NULL;
00311 
00312             switch(cn->typ) {
00313             case GWEN_DB_NodeType_ValueChar:
00314               typname="char ";
00315               pvalue=cn->data.dataChar;
00316               if (dbflags & GWEN_DB_FLAGS_ESCAPE_CHARVALUES) {
00317                 vbuf=GWEN_Buffer_new(0, strlen(pvalue)+32, 0, 1);
00318                 if (GWEN_Text_EscapeToBufferTolerant(pvalue, vbuf)) {
00319                   DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00320                   GWEN_Buffer_free(vbuf);
00321                   return 1;
00322                 }
00323                 pvalue=GWEN_Buffer_GetStart(vbuf);
00324               }
00325               break;
00326 
00327             case GWEN_DB_NodeType_ValueInt:
00328               typname="int  ";
00329               if (GWEN_Text_NumToString(cn->data.dataInt,
00330                                         numbuffer,
00331                                         sizeof(numbuffer)-1,
00332                                         0)<1) {
00333                 DBG_ERROR(GWEN_LOGDOMAIN, "Error writing numeric value");
00334                 return GWEN_ERROR_GENERIC;
00335               }
00336               pvalue=numbuffer;
00337               break;
00338 
00339             case GWEN_DB_NodeType_ValueBin:
00340               bbsize=cn->dataSize*2+1;
00341               binbuffer=(char*)GWEN_Memory_malloc(bbsize);
00342               assert(binbuffer);
00343               typname="bin  ";
00344               if (!GWEN_Text_ToHex(cn->data.dataBin,
00345                                    cn->dataSize,
00346                                    binbuffer,
00347                                    bbsize)) {
00348                 DBG_ERROR(GWEN_LOGDOMAIN, "Error writing binary value");
00349                 return GWEN_ERROR_GENERIC;
00350               }
00351               pvalue=binbuffer;
00352               break;
00353 
00354             case GWEN_DB_NodeType_ValuePtr:
00355               DBG_DEBUG(GWEN_LOGDOMAIN, "Not writing ptr type");
00356               break;
00357 
00358             default:
00359               DBG_DEBUG(GWEN_LOGDOMAIN, "Unhandled type [%d]", cn->typ);
00360               break;
00361             }
00362 
00363             if (pvalue) {
00364               if (!namewritten) {
00365                 /* write name */
00366                 /* indend */
00367                 if (dbflags & GWEN_DB_FLAGS_INDEND) {
00368                   for (i=0; i<insert; i++) {
00369                     GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' ');
00370                     if (err<0) {
00371                       DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00372                       GWEN_Memory_dealloc(binbuffer);
00373                       GWEN_Buffer_free(vbuf);
00374                       return 1;
00375                     }
00376                   } /* for */
00377                 } /* if indend */
00378                 if (!(dbflags & GWEN_DB_FLAGS_OMIT_TYPES)) {
00379                   GWEN_FASTBUFFER_WRITEFORCED(fb, err, typname, -1);
00380                   if (err<0) {
00381                     DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00382                     GWEN_Memory_dealloc(binbuffer);
00383                     GWEN_Buffer_free(vbuf);
00384                     return 1;
00385                   }
00386                 }
00387                 if (dbflags & GWEN_DB_FLAGS_QUOTE_VARNAMES) {
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                 GWEN_FASTBUFFER_WRITEFORCED(fb, err, n->data.dataName, -1);
00397                 if (err<0) {
00398                   DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00399                   GWEN_Memory_dealloc(binbuffer);
00400                   GWEN_Buffer_free(vbuf);
00401                   return 1;
00402                 }
00403                 if (dbflags & GWEN_DB_FLAGS_QUOTE_VARNAMES) {
00404                   GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
00405                   if (err<0) {
00406                     DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00407                     GWEN_Memory_dealloc(binbuffer);
00408                     GWEN_Buffer_free(vbuf);
00409                     return 1;
00410                   }
00411                 }
00412                 GWEN_FASTBUFFER_WRITEFORCED(fb, err, ((dbflags & GWEN_DB_FLAGS_USE_COLON)?": ":"="), -1);
00413                 if (err<0) {
00414                   DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00415                   GWEN_Memory_dealloc(binbuffer);
00416                   GWEN_Buffer_free(vbuf);
00417                   return 1;
00418                 }
00419                 namewritten=1;
00420               } /* if !namewritten */
00421 
00422               if (values) {
00423                 GWEN_FASTBUFFER_WRITEFORCED(fb, err, ", ", -1);
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               values++;
00432               if (dbflags & GWEN_DB_FLAGS_QUOTE_VALUES) {
00433                 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
00434                 if (err<0) {
00435                   DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00436                   GWEN_Memory_dealloc(binbuffer);
00437                   GWEN_Buffer_free(vbuf);
00438                   return 1;
00439                 }
00440               }
00441 
00442               GWEN_FASTBUFFER_WRITEFORCED(fb, err, pvalue, -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               if (dbflags & GWEN_DB_FLAGS_QUOTE_VALUES) {
00451                 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
00452                 if (err<0) {
00453                   DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00454                   GWEN_Memory_dealloc(binbuffer);
00455                   GWEN_Buffer_free(vbuf);
00456                   return 1;
00457                 }
00458               }
00459             } /* if pvalue */
00460 
00461             GWEN_Memory_dealloc(binbuffer);
00462             GWEN_Buffer_free(vbuf);
00463             cn=GWEN_DB_Node_List_Next(cn);
00464           } /* while cn */
00465 
00466           if (namewritten) {
00467             GWEN_FASTBUFFER_WRITELINE(fb, err, "");
00468             if (err<0) {
00469               DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00470               return GWEN_ERROR_GENERIC;
00471             }
00472           }
00473         } /* if children */
00474         lastWasVar=1;
00475         break;
00476 
00477       default:
00478         DBG_WARN(GWEN_LOGDOMAIN, "[unhandled node type %d]", n->typ);
00479       } /* switch */
00480     } /* if not volatile */
00481     else {
00482       DBG_DEBUG(GWEN_LOGDOMAIN, "Node is volatile, not writing it");
00483     }
00484     n=GWEN_DB_Node_List_Next(n);
00485   } /* while */
00486 
00487   return 0;
00488 }
00489 
00490 
00491 
00492 int GWEN_DB_WriteToFastBuffer(GWEN_DB_NODE *node,
00493                               GWEN_FAST_BUFFER *fb,
00494                               uint32_t dbflags) {
00495   int rv;
00496 
00497   rv=GWEN_DB_WriteGroupToIoLayer(node, fb, dbflags, 0);
00498   if (rv<0) {
00499     return rv;
00500   }
00501   GWEN_FASTBUFFER_FLUSH(fb, rv);
00502   return rv;
00503 }
00504 
00505 
00506 
00507 int GWEN_DB_WriteToIo(GWEN_DB_NODE *node,
00508                       GWEN_SYNCIO *sio,
00509                       uint32_t dbflags) {
00510   int rv;
00511   GWEN_FAST_BUFFER *fb;
00512 
00513   fb=GWEN_FastBuffer_new(512, sio);
00514   if (dbflags & GWEN_DB_FLAGS_DOSMODE)
00515     GWEN_FastBuffer_AddFlags(fb, GWEN_FAST_BUFFER_FLAGS_DOSMODE);
00516   rv=GWEN_DB_WriteGroupToIoLayer(node, fb, dbflags, 0);
00517   if (rv<0) {
00518     GWEN_FastBuffer_free(fb);
00519     return rv;
00520   }
00521   GWEN_FASTBUFFER_FLUSH(fb, rv);
00522   GWEN_FastBuffer_free(fb);
00523   return rv;
00524 }
00525 
00526 
00527 
00528 int GWEN_DB_WriteFile(GWEN_DB_NODE *n, const char *fname, uint32_t dbflags){
00529   int rv;
00530   GWEN_FSLOCK *lck=0;
00531   GWEN_SYNCIO *sio;
00532 
00533   /* if locking requested */
00534   if (dbflags & GWEN_DB_FLAGS_LOCKFILE) {
00535     GWEN_FSLOCK_RESULT res;
00536 
00537     lck=GWEN_FSLock_new(fname, GWEN_FSLock_TypeFile);
00538     assert(lck);
00539     res=GWEN_FSLock_Lock(lck, GWEN_DB_DEFAULT_LOCK_TIMEOUT, 0);
00540     if (res!=GWEN_FSLock_ResultOk) {
00541       DBG_ERROR(GWEN_LOGDOMAIN,
00542                 "Could not apply lock to file \"%s\" (%d)",
00543                 fname, res);
00544       GWEN_FSLock_free(lck);
00545       return -1;
00546     }
00547   }
00548 
00549   /* open file */
00550   sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_CreateAlways);
00551   if (dbflags & GWEN_DB_FLAGS_APPEND_FILE)
00552     GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_APPEND);
00553   GWEN_SyncIo_AddFlags(sio,
00554                        GWEN_SYNCIO_FILE_FLAGS_READ |
00555                        GWEN_SYNCIO_FILE_FLAGS_WRITE |
00556                        GWEN_SYNCIO_FILE_FLAGS_UREAD |
00557                        GWEN_SYNCIO_FILE_FLAGS_UWRITE);
00558   rv=GWEN_SyncIo_Connect(sio);
00559   if (rv<0) {
00560     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00561     GWEN_SyncIo_free(sio);
00562     if (lck) {
00563       GWEN_FSLock_Unlock(lck);
00564       GWEN_FSLock_free(lck);
00565     }
00566     return rv;
00567   }
00568 
00569   rv=GWEN_DB_WriteToIo(n, sio, dbflags);
00570   if (rv<0) {
00571     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00572     GWEN_SyncIo_Disconnect(sio);
00573     GWEN_SyncIo_free(sio);
00574     if (lck) {
00575       GWEN_FSLock_Unlock(lck);
00576       GWEN_FSLock_free(lck);
00577     }
00578     return rv;
00579   }
00580 
00581   rv=GWEN_SyncIo_Disconnect(sio);
00582   if (rv<0) {
00583     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00584     GWEN_SyncIo_free(sio);
00585     if (lck) {
00586       GWEN_FSLock_Unlock(lck);
00587       GWEN_FSLock_free(lck);
00588     }
00589     return rv;
00590   }
00591   GWEN_SyncIo_free(sio);
00592 
00593   /* remove lock, if any */
00594   if (lck) {
00595     GWEN_FSLOCK_RESULT res;
00596 
00597     res=GWEN_FSLock_Unlock(lck);
00598     if (res!=GWEN_FSLock_ResultOk) {
00599       DBG_WARN(GWEN_LOGDOMAIN,
00600                "Could not remove lock on file \"%s\" (%d)",
00601                fname, res);
00602     }
00603     GWEN_FSLock_free(lck);
00604   }
00605 
00606   return 0;
00607 }
00608 
00609 
00610 
00611 int GWEN_DB__ReadValues(GWEN_DB_NODE *n,
00612                         uint32_t dbflags,
00613                         const char *typeName,
00614                         const char *varName,
00615                         uint8_t *p) {
00616   GWEN_DB_NODE_TYPE nodeType=GWEN_DB_NodeType_ValueChar;
00617   GWEN_DB_NODE *dbVar;
00618   GWEN_BUFFER *wbuf;
00619   uint8_t *pDebug;
00620 
00621   pDebug=p;
00622 
00623   if (typeName==NULL)
00624     typeName="char";
00625   if (strcasecmp(typeName, "int")==0)
00626     nodeType=GWEN_DB_NodeType_ValueInt;
00627   else if (strcasecmp(typeName, "char")==0)
00628     nodeType=GWEN_DB_NodeType_ValueChar;
00629   else if (strcasecmp(typeName, "bin")==0)
00630     nodeType=GWEN_DB_NodeType_ValueBin;
00631   else {
00632     DBG_ERROR(GWEN_LOGDOMAIN, "Unknown type \"%s\"", typeName);
00633     return GWEN_ERROR_BAD_DATA;
00634   }
00635 
00636   dbVar=GWEN_DB_GetNode(n, varName, dbflags | GWEN_PATH_FLAGS_VARIABLE);
00637   if (dbVar==NULL) {
00638     DBG_INFO(GWEN_LOGDOMAIN, "Variable [%s] is not available", varName);
00639     return GWEN_ERROR_GENERIC;
00640   }
00641 
00642   wbuf=GWEN_Buffer_new(0, 32, 0, 1);
00643   for (;;) {
00644     int quotes=0;
00645     GWEN_DB_NODE *dbVal=NULL;
00646     const char *v;
00647 
00648     while(*p && isspace(*p))
00649       p++;
00650     if (!*p) {
00651       DBG_INFO(GWEN_LOGDOMAIN, "Missing value");
00652       GWEN_Buffer_free(wbuf);
00653       return GWEN_ERROR_BAD_DATA;
00654     }
00655 
00656     if (*p=='"') {
00657       quotes=1;
00658       p++;
00659     }
00660 
00661     while(*p) {
00662       if (*p=='%') {
00663         uint8_t c;
00664         uint8_t cHex;
00665 
00666         /* get first nibble */
00667         p++;
00668         if (!*p) {
00669           DBG_INFO(GWEN_LOGDOMAIN, "Incomplete escape sequence");
00670           GWEN_Buffer_free(wbuf);
00671           return GWEN_ERROR_BAD_DATA;
00672         }
00673         c=toupper(*p)-'0';
00674         if (c>9) c-=7;
00675         cHex=c<<4;
00676 
00677         p++;
00678         if (!*p) {
00679           DBG_INFO(GWEN_LOGDOMAIN, "Incomplete escape sequence");
00680           GWEN_Buffer_free(wbuf);
00681           return GWEN_ERROR_BAD_DATA;
00682         }
00683         c=toupper(*p)-'0';
00684         if (c>9) c-=7;
00685         cHex|=c;
00686         GWEN_Buffer_AppendByte(wbuf, cHex);
00687       }
00688       else
00689         if (quotes) {
00690           if (*p=='"') {
00691             p++;
00692             break;
00693           }
00694           else
00695             GWEN_Buffer_AppendByte(wbuf, *p);
00696         }
00697         else {
00698           if (*p==',' || *p==';' || *p=='#')
00699             break;
00700           else if (*p=='"') {
00701             DBG_INFO(GWEN_LOGDOMAIN, "Unexpected quotation mark (Line: [%s], parsed: [%s]",
00702                      pDebug, GWEN_Buffer_GetStart(wbuf));
00703             GWEN_Buffer_free(wbuf);
00704             return GWEN_ERROR_BAD_DATA;
00705           }
00706           else
00707             GWEN_Buffer_AppendByte(wbuf, *p);
00708         }
00709       p++;
00710     }
00711 
00712     v=GWEN_Buffer_GetStart(wbuf);
00713     if (nodeType==GWEN_DB_NodeType_ValueInt) {
00714       int i;
00715 
00716       if (1!=sscanf(v, "%d", &i)) {
00717         DBG_INFO(GWEN_LOGDOMAIN, "Not an integer value [%s]", v);
00718         GWEN_Buffer_free(wbuf);
00719         return GWEN_ERROR_BAD_DATA;
00720       }
00721       dbVal=GWEN_DB_ValueInt_new(i);
00722     }
00723     else if (nodeType==GWEN_DB_NodeType_ValueChar)
00724       dbVal=GWEN_DB_ValueChar_new(v);
00725     else if (nodeType==GWEN_DB_NodeType_ValueBin) {
00726       GWEN_BUFFER *bbuf;
00727       int rv;
00728 
00729       bbuf=GWEN_Buffer_new(0, (GWEN_Buffer_GetUsedBytes(wbuf)/2)+1, 0, 1);
00730       rv=GWEN_Text_FromHexBuffer(v, bbuf);
00731       if (rv) {
00732         DBG_INFO(GWEN_LOGDOMAIN, "Bad bin value [%s]", v);
00733         GWEN_Buffer_free(bbuf);
00734         GWEN_Buffer_free(wbuf);
00735         return GWEN_ERROR_BAD_DATA;
00736       }
00737       dbVal=GWEN_DB_ValueBin_new(GWEN_Buffer_GetStart(bbuf),
00738                                  GWEN_Buffer_GetUsedBytes(bbuf));
00739       GWEN_Buffer_free(bbuf);
00740     }
00741     else {
00742       /* should never reach this point */
00743       assert(0);
00744     }
00745     GWEN_DB_Node_Append(dbVar, dbVal);
00746 
00747     /* skip blanks if any */
00748     while(*p && isspace(*p))
00749       p++;
00750     if (!*p || *p==';' || *p=='#')
00751       break;
00752     else if (*p!=',') {
00753       DBG_INFO(GWEN_LOGDOMAIN, "Unexpected character [%s]", p);
00754       GWEN_Buffer_free(wbuf);
00755       return GWEN_ERROR_BAD_DATA;
00756     }
00757     p++;
00758     GWEN_Buffer_Reset(wbuf);
00759   }
00760 
00761   GWEN_Buffer_free(wbuf);
00762   return 0;
00763 }
00764 
00765 
00766 
00767 int GWEN_DB_ReadFromFastBuffer(GWEN_DB_NODE *n,
00768                                GWEN_FAST_BUFFER *fb,
00769                                uint32_t dbflags) {
00770   GWEN_BUFFER *lbuf;
00771   GWEN_BUFFER *tbuf;
00772   int level=0;
00773   int someLinesRead=0;
00774 
00775   lbuf=GWEN_Buffer_new(0, 128, 0, 1);
00776   tbuf=GWEN_Buffer_new(0, 128, 0, 1);
00777 
00778   for (;;) {
00779     int rv;
00780     uint8_t *p;
00781 
00782     rv=GWEN_FastBuffer_ReadLineToBuffer(fb, lbuf);
00783     if (rv<0) {
00784       if (rv==GWEN_ERROR_EOF) {
00785         if (!someLinesRead && !(dbflags & GWEN_DB_FLAGS_ALLOW_EMPTY_STREAM)){
00786           DBG_INFO(GWEN_LOGDOMAIN, "Unexpected EOF (%d)", rv);
00787           GWEN_Buffer_free(tbuf);
00788           GWEN_Buffer_free(lbuf);
00789           return rv;
00790         }
00791         break;
00792       }
00793       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00794       GWEN_Buffer_free(tbuf);
00795       GWEN_Buffer_free(lbuf);
00796       return rv;
00797     }
00798 
00799     if (GWEN_Buffer_GetUsedBytes(lbuf)==0) {
00800       if (dbflags & GWEN_DB_FLAGS_UNTIL_EMPTY_LINE) {
00801         break;
00802       }
00803     }
00804     else {
00805       someLinesRead=1;
00806       p=(uint8_t*)GWEN_Buffer_GetStart(lbuf);
00807       while(*p && isspace(*p))
00808         p++;
00809       if (*p) {
00810         uint8_t *p1begin=NULL, *p1end=NULL;
00811         uint8_t *p2begin=NULL, *p2end=NULL;
00812   
00813         /* non-empty line */
00814         if (*p=='}') {
00815           /* found end of current group */
00816           if (level<1) {
00817             DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket");
00818             GWEN_Buffer_free(tbuf);
00819             GWEN_Buffer_free(lbuf);
00820             return GWEN_ERROR_BAD_DATA;
00821           }
00822           n=n->parent;
00823           assert(n); /* internal error if parent not found */
00824           assert(n->typ==GWEN_DB_NodeType_Group); /* internal error if parent is not a group */
00825           level--;
00826         }
00827         else if (*p=='#') {
00828           /* comment only line */
00829         }
00830         else {
00831           p1begin=p;
00832           /* read first token */
00833           while(*p && !isspace(*p) &&
00834                 *p!='{' &&
00835                 *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') &&
00836                 *p!='}' &&
00837                 *p!=',' &&
00838                 *p!=';')
00839             p++;
00840           if (!*p) {
00841               DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token (first: \"%s\")", p1begin);
00842             GWEN_Buffer_Dump(lbuf, 2);
00843             GWEN_Buffer_free(tbuf);
00844             GWEN_Buffer_free(lbuf);
00845             return GWEN_ERROR_BAD_DATA;
00846           }
00847           p1end=p;
00848 
00849           /* get to start of 2nd token */
00850           while(*p && isspace(*p))
00851             p++;
00852           if (!*p) {
00853             DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token");
00854             GWEN_Buffer_free(tbuf);
00855             GWEN_Buffer_free(lbuf);
00856             return GWEN_ERROR_BAD_DATA;
00857           }
00858   
00859           if (*p=='{') {
00860             GWEN_DB_NODE *newGr;
00861   
00862             /* found start of group */
00863             *p1end=0;
00864             rv=GWEN_DB_UnescapeToBufferTolerant((const char*)p1begin, tbuf);
00865             if (rv<0) {
00866               DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00867               GWEN_Buffer_free(tbuf);
00868               GWEN_Buffer_free(lbuf);
00869               return rv;
00870             }
00871             newGr=GWEN_DB_GetGroup(n, dbflags, GWEN_Buffer_GetStart(tbuf));
00872             if (newGr==NULL) {
00873               DBG_INFO(GWEN_LOGDOMAIN, "Could not create group [%s]", GWEN_Buffer_GetStart(tbuf));
00874               GWEN_Buffer_free(tbuf);
00875               GWEN_Buffer_free(lbuf);
00876               return GWEN_ERROR_GENERIC;
00877             }
00878             GWEN_Buffer_Reset(tbuf);
00879             n=newGr;
00880             level++;
00881           }
00882           else if (*p=='=' || *p==':') {
00883             /* found short variable definition */
00884             *p1end=0;
00885             p++;
00886             rv=GWEN_DB__ReadValues(n, dbflags, NULL, (const char*)p1begin, p);
00887             if (rv) {
00888               DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00889               GWEN_Buffer_free(tbuf);
00890               GWEN_Buffer_free(lbuf);
00891               return rv;
00892             }
00893           }
00894           else if (*p==',' || *p==';') {
00895             DBG_INFO(GWEN_LOGDOMAIN, "Unexpected delimiter found");
00896             GWEN_Buffer_free(tbuf);
00897             GWEN_Buffer_free(lbuf);
00898             return GWEN_ERROR_BAD_DATA;
00899           }
00900           else {
00901             /* 2nd token, so this should be a standard variable definition */
00902             p2begin=p;
00903             while(*p &&
00904                   !isspace(*p) &&
00905                   *p!='{' &&
00906                   *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') &&
00907                   *p!='}' &&
00908                   *p!=',' &&
00909                   *p!=';')
00910               p++;
00911             if (!*p) {
00912               DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token [%s], [%s]", p1begin, p2begin);
00913               GWEN_Buffer_free(tbuf);
00914               GWEN_Buffer_free(lbuf);
00915               return GWEN_ERROR_BAD_DATA;
00916             }
00917             p2end=p;
00918             if (isspace(*p)) {
00919               while(*p && isspace(*p))
00920                 p++;
00921               if (!*p) {
00922                 DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token");
00923                 GWEN_Buffer_free(tbuf);
00924                 GWEN_Buffer_free(lbuf);
00925                 return GWEN_ERROR_BAD_DATA;
00926               }
00927             }
00928             if (*p!='=' && *p!=':') {
00929               DBG_INFO(GWEN_LOGDOMAIN, "Equation mark expected");
00930               GWEN_Buffer_free(tbuf);
00931               GWEN_Buffer_free(lbuf);
00932               return GWEN_ERROR_BAD_DATA;
00933             }
00934             p++;
00935   
00936             *p1end=0;
00937             *p2end=0;
00938             rv=GWEN_DB__ReadValues(n, dbflags, (const char*)p1begin, (const char*)p2begin, p);
00939             if (rv) {
00940               DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00941               GWEN_Buffer_free(tbuf);
00942               GWEN_Buffer_free(lbuf);
00943               return rv;
00944             }
00945           }
00946         }
00947       }
00948     }
00949     GWEN_Buffer_Reset(lbuf);
00950   }
00951 
00952   if (level) {
00953     DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket (too few)");
00954     GWEN_Buffer_free(tbuf);
00955     GWEN_Buffer_free(lbuf);
00956     return GWEN_ERROR_BAD_DATA;
00957   }
00958 
00959   GWEN_Buffer_free(tbuf);
00960   GWEN_Buffer_free(lbuf);
00961 
00962   return 0;
00963 }
00964 
00965 
00966 
00967 int GWEN_DB_ReadFromIo(GWEN_DB_NODE *n, GWEN_SYNCIO *sio, uint32_t dbflags) {
00968   GWEN_FAST_BUFFER *fb;
00969   int rv;
00970 
00971   /* prepare fast buffer */
00972   fb=GWEN_FastBuffer_new(1024, sio);
00973   if (dbflags & GWEN_DB_FLAGS_DOSMODE)
00974     GWEN_FastBuffer_AddFlags(fb, GWEN_FAST_BUFFER_FLAGS_DOSMODE);
00975 
00976   /* read from it */
00977   rv=GWEN_DB_ReadFromFastBuffer(n, fb, dbflags);
00978   if (rv<0) {
00979     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00980     GWEN_FastBuffer_free(fb);
00981     return rv;
00982   }
00983 
00984   GWEN_FastBuffer_free(fb);
00985 
00986   return 0;
00987 }
00988 
00989 
00990 
00991 int GWEN_DB_ReadFile(GWEN_DB_NODE *n,
00992                      const char *fname,
00993                      uint32_t dbflags) {
00994   GWEN_SYNCIO *sio;
00995   int rv;
00996 
00997   sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting);
00998   GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
00999   rv=GWEN_SyncIo_Connect(sio);
01000   if (rv<0) {
01001     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01002     GWEN_SyncIo_free(sio);
01003     return rv;
01004   }
01005 
01006   /* read from it */
01007   rv=GWEN_DB_ReadFromIo(n, sio, dbflags);
01008   if (rv<0) {
01009     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01010     GWEN_SyncIo_Disconnect(sio);
01011     GWEN_SyncIo_free(sio);
01012     return rv;
01013   }
01014 
01015   GWEN_SyncIo_Disconnect(sio);
01016   GWEN_SyncIo_free(sio);
01017   return 0;
01018 }
01019 
01020 
01021 
01022 int GWEN_DB_ReadFromString(GWEN_DB_NODE *n,
01023                            const char *str,
01024                            int len,
01025                            uint32_t dbflags) {
01026   GWEN_SYNCIO *sio;
01027   int rv;
01028 
01029   if (len==0)
01030     len=strlen(str);
01031 
01032   sio=GWEN_SyncIo_Memory_fromBuffer((const uint8_t*) str, len);
01033   rv=GWEN_DB_ReadFromIo(n, sio, dbflags);
01034   if (rv<0) {
01035     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01036     GWEN_SyncIo_free(sio);
01037     return rv;
01038   }
01039 
01040   GWEN_SyncIo_free(sio);
01041 
01042   return 0;
01043 }
01044 
01045 
01046 
01047 int GWEN_DB_WriteToBuffer(GWEN_DB_NODE *n,
01048                           GWEN_BUFFER *buf,
01049                           uint32_t dbflags) {
01050   GWEN_SYNCIO *sio;
01051   int rv;
01052 
01053   /* create SyncIO, don't take over buf */
01054   sio=GWEN_SyncIo_Memory_new(buf, 0);
01055   rv=GWEN_DB_WriteToIo(n, sio, dbflags);
01056   if (rv<0) {
01057     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01058     GWEN_SyncIo_free(sio);
01059     return rv;
01060   }
01061 
01062   GWEN_SyncIo_free(sio);
01063   return 0;
01064 }
01065 
01066 
01067 
01068 
01069 
01070 
01071 
01072 
01073 
01074 
01075 
01076