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 #ifdef HAVE_CONFIG_H
00027 #include "config.h"
00028 #endif
00029 #include "kdb.h"
00030 #include "kdbbackend.h"
00031 #include "kdbprivate.h"
00032
00033 #include <stdlib.h>
00034 #include <stdarg.h>
00035 #include "kdbLibLoader.h"
00036
00037 #ifdef HAVE_UNISTD_H
00038 #include <unistd.h>
00039 #endif
00040 #include <errno.h>
00041 #include <stdio.h>
00042 #ifdef HAVE_ICONV
00043 #include <iconv.h>
00044 #endif
00045 #ifdef HAVE_LOCALE_H
00046 #include <locale.h>
00047 #endif
00048 #ifdef HAVE_LANGINFO_H
00049 #include <langinfo.h>
00050 #endif
00051 #include <ctype.h>
00052 #include <string.h>
00053
00054
00055 #ifdef WIN32
00056 #define usleep(x) Sleep(x)
00057 #endif
00058
00059
00060
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 struct _KDBBackend {
00100 kdbLibHandle dlHandle;
00101
00102 char *name;
00103
00104
00105
00106 kdbOpenPtr kdbOpen;
00107 kdbClosePtr kdbClose;
00108
00109 kdbGetKeyPtr kdbGetKey;
00110 kdbSetKeyPtr kdbSetKey;
00111 kdbStatKeyPtr kdbStatKey;
00112 kdbRenamePtr kdbRename;
00113 kdbRemoveKeyPtr kdbRemoveKey;
00114 kdbGetChildKeysPtr kdbGetKeyChildKeys;
00115
00116
00117
00118
00119 kdbSetKeysPtr kdbSetKeys;
00120 kdbMonitorKeyPtr kdbMonitorKey;
00121 kdbMonitorKeysPtr kdbMonitorKeys;
00122 };
00123
00124
00125
00126
00127 KDBBackend *backend;
00128
00129
00130
00160 int kdbOpen() {
00161 char *backendName=0;
00162
00163 backendName=getenv("KDB_BACKEND");
00164 if (backendName) return kdbOpenBackend(backendName);
00165 else return kdbOpenBackend(DEFAULT_BACKEND);
00166 }
00167
00168
00169
00188 int kdbOpenDefault() {
00189 return kdbOpenBackend(DEFAULT_BACKEND);
00190 }
00191
00192
00193
00194
00244 int kdbOpenBackend(char *backendName) {
00245 kdbLibHandle dlhandle=0;
00246 char backendlib[300];
00247 KDBBackendFactory kdbBackendNew=0;
00248 int rc=0;
00249
00250 backend=0;
00251
00252
00253 #ifdef HAVE_SETLOCALE
00254 setlocale(LC_ALL,"");
00255 #endif
00256
00257
00258 if ( (rc = kdbLibInit()) ) {
00259 errno=KDB_RET_NOSYS;
00260 return 1;
00261 }
00262
00263 sprintf(backendlib,"libelektra-%s",backendName);
00264 dlhandle=kdbLibLoad(backendlib);
00265 if (dlhandle == 0) {
00266 errno=KDB_RET_NOSYS;
00267 return 1;
00268 }
00269
00270 kdbBackendNew=(KDBBackendFactory)kdbLibSym(dlhandle,"kdbBackendFactory");
00271 if (kdbBackendNew == 0) {
00272 errno=KDB_RET_NOSYS;
00273 return 2;
00274 }
00275
00276 backend=(*kdbBackendNew)();
00277 if (backend == 0) {
00278 fprintf(stderr,"libelektra: Can't initialize \"%s\" backend\n",
00279 backendName);
00280 errno=KDB_RET_NOSYS;
00281 return 3;
00282 }
00283
00284
00285 backend->dlHandle=dlhandle;
00286
00287
00288 if (backend->kdbOpen) rc=backend->kdbOpen();
00289 else {
00290 errno=KDB_RET_NOSYS;
00291 rc=4;
00292 }
00293 return rc;
00294 }
00295
00296
00297
00311 int kdbClose() {
00312 int rc=0;
00313
00314 if (backend && backend->kdbClose) rc=backend->kdbClose();
00315 else {
00316 errno=KDB_RET_NOSYS;
00317 return -1;
00318 }
00319
00320 if (rc == 0) {
00321 if (backend->name) free(backend->name);
00322 kdbLibClose(backend->dlHandle);
00323 free(backend); backend=0;
00324 }
00325
00326 return rc;
00327 }
00328
00329
00330
00331
00349 ssize_t unencode(char *encoded,void *returned) {
00350 char byteInHexa[5]="0x";
00351 char *readCursor=encoded;
00352 char *writeCursor=returned;
00353
00354 if (!encoded) {
00355 if (returned) *(char *)returned=0;
00356 return 0;
00357 }
00358
00359 byteInHexa[4]=0;
00360 while (*readCursor) {
00361 if (isspace((int)*readCursor))
00362 {
00363 readCursor++;
00364 continue;
00365 }
00366 if (isxdigit((int)*readCursor)) {
00367 long int converted;
00368 byteInHexa[2]=readCursor[0];
00369 byteInHexa[3]=readCursor[1];
00370 converted=strtol(byteInHexa,0,16);
00371 *writeCursor=(unsigned char)converted;
00372
00373 readCursor+=2;
00374 writeCursor++;
00375 } else {
00376
00377 errno=KDB_RET_TYPEMISMATCH;
00378 return -1;
00379 }
00380 }
00381 return (long int)writeCursor-(long int)returned;
00382 }
00383
00395 int kdbNeedsUTF8Conversion() {
00396 #if defined(HAVE_NL_LANGINFO) && defined(HAVE_ICONV) && defined(CODESET)
00397 return strcmp(nl_langinfo(CODESET),"UTF-8");
00398 #else
00399 return 0;
00400 #endif
00401 }
00402
00403
00428 int UTF8Engine(int direction, char **string, size_t *inputOutputByteSize) {
00429
00430
00431
00432
00433
00434 #if defined(HAVE_ICONV_H) && defined(HAVE_NL_LANGINFO) && defined(CODESET)
00435 char *currentCharset=0;
00436 char *converted=0;
00437 char *readCursor, *writeCursor;
00438 size_t bufferSize;
00439 iconv_t converter;
00440
00441 if (kdbNeedsUTF8Conversion()) currentCharset=nl_langinfo(CODESET);
00442 else return 0;
00443
00444 if (direction==UTF8_TO) converter=iconv_open("UTF-8",currentCharset);
00445 else converter=iconv_open(currentCharset,"UTF-8");
00446
00447 if (converter == (iconv_t)(-1)) return -1;
00448
00449
00450 bufferSize=*inputOutputByteSize * 4;
00451 converted=malloc(bufferSize);
00452 if (!converted) return -1;
00453
00454 readCursor=*string;
00455 writeCursor=converted;
00456
00457
00458 if (iconv(converter,
00459 (ICONV_CONST char **)&readCursor,inputOutputByteSize,
00460 &writeCursor,&bufferSize) == (size_t)(-1)) {
00461 free(converted);
00462 iconv_close(converter);
00463 return -1;
00464 }
00465
00466
00467 *inputOutputByteSize=writeCursor-converted;
00468
00469 readCursor=*string;
00470
00471 *string=malloc(*inputOutputByteSize);
00472
00473 memcpy(*string,converted,*inputOutputByteSize);
00474
00475 free(readCursor);
00476
00477 free(converted);
00478
00479 iconv_close(converter);
00480 #endif
00481 return 0;
00482 }
00483
00484
00485
00504 ssize_t encode(void *unencoded, size_t size, char *returned) {
00505 char *readCursor=unencoded;
00506 char *writeCursor=returned;
00507 int blockStep=4;
00508 int lineStep=8*blockStep;
00509 int currentInBlock=0;
00510 int currentInLine=0;
00511
00512 while ((readCursor-(char *)unencoded)<size) {
00513 sprintf(writeCursor,"%02x",*(unsigned char *)readCursor);
00514 readCursor++;
00515 writeCursor+=2;
00516 currentInBlock++;
00517 currentInLine++;
00518 if (currentInLine==lineStep) {
00519 *writeCursor='\n'; writeCursor++;
00520 currentInLine=0;
00521 currentInBlock=0;
00522 }
00523 if (currentInBlock==blockStep) {
00524 *writeCursor=' '; writeCursor++;
00525 currentInBlock=0;
00526 }
00527 }
00528 *writeCursor='\n';
00529 *++writeCursor=0;
00530 return writeCursor-returned;
00531 }
00532
00533
00534
00535
00536
00550 int kdbGetValue(const char *keyname, char *returned,size_t maxSize) {
00551 Key *key;
00552 int rc=0;
00553
00554 key=keyNew(keyname,KEY_SWITCH_END);
00555 rc=kdbGetKey(key);
00556 if (rc == 0) keyGetString(key,returned,maxSize);
00557 else rc=errno;
00558 keyDel(key);
00559 errno=rc;
00560 return rc;
00561 }
00562
00563
00564
00578 int kdbSetValue(const char *keyname, const char *value) {
00579 Key *key;
00580 int rc;
00581
00582
00583 key=keyNew(keyname,KEY_SWITCH_END);
00584 rc=kdbGetKey(key);
00585 keySetString(key,value);
00586 rc=kdbSetKey(key);
00587 keyDel(key);
00588 return rc;
00589 }
00590
00591
00592
00619 int kdbGetValueByParent(const char *parentName, const char *baseName, char *returned, size_t maxSize) {
00620 char *name;
00621 int retval=0;
00622 name = (char *)malloc(sizeof(char)*(strblen(parentName)+strblen(baseName)));
00623
00624 sprintf(name,"%s/%s",parentName,baseName);
00625 retval = kdbGetValue(name,returned,maxSize);
00626 free(name);
00627 return retval;
00628 }
00629
00630
00631
00642 int kdbSetValueByParent(const char *parentName, const char *baseName, const char *value) {
00643 char *name;
00644 int retval=0;
00645 name = (char *)malloc(sizeof(char)*(strblen(parentName)+strblen(baseName)));
00646
00647 sprintf(name,"%s/%s",parentName,baseName);
00648 retval = kdbSetValue(name,value);
00649 free(name);
00650 return retval;
00651 }
00652
00653
00654
00669 int kdbGetKeyByParent(const char *parentName, const char *baseName, Key *returned) {
00670 char *name;
00671 name = (char *)malloc(sizeof(char) * (strblen(parentName)+strblen(baseName)));
00672
00673 sprintf(name,"%s/%s",parentName,baseName);
00674 keySetName(returned,name);
00675 free(name);
00676 return kdbGetKey(returned);
00677 }
00678
00679
00687 int kdbGetKeyByParentKey(const Key *parent, const char *baseName, Key *returned) {
00688 size_t size=keyGetFullNameSize(parent);
00689 char *name;
00690 name = (char *)malloc(sizeof(char) * (size+strblen(baseName)));
00691
00692 keyGetFullName(parent,name,size);
00693 name[size-1]='/';
00694 strcpy((char *)(name+size),baseName);
00695
00696 keySetName(returned,name);
00697 free(name);
00698 return kdbGetKey(returned);
00699 }
00700
00701
00702
00703
00704
00793 ssize_t kdbGetKeyChildKeys(const Key *parentKey, KeySet *returned, unsigned long options) {
00794
00795 if (backend && backend->kdbGetKeyChildKeys)
00796 return backend->kdbGetKeyChildKeys(parentKey,returned,options);
00797 else {
00798 errno=KDB_RET_NOSYS;
00799 return -1;
00800 }
00801 }
00802
00803
00804
00810 ssize_t kdbGetChildKeys(const char *parentName, KeySet *returned, unsigned long options) {
00811 Key *parentKey;
00812 ssize_t rc;
00813
00814 parentKey=keyNew(parentName,KEY_SWITCH_END);
00815 rc=kdbGetKeyChildKeys(parentKey,returned,options);
00816
00817 keyDel(parentKey);
00818
00819 return rc;
00820 }
00821
00822
00823
00835 ssize_t kdbGetRootKeys(KeySet *returned) {
00836 Key *system=0,*user=0;
00837
00838 user=keyNew("user",KEY_SWITCH_NEEDSYNC,KEY_SWITCH_END);
00839 if (user->flags & KEY_SWITCH_FLAG) {
00840 keyDel(user);
00841 user=0;
00842 } else ksInsert(returned,user);
00843
00844 system=keyNew("system",KEY_SWITCH_NEEDSYNC,KEY_SWITCH_END);
00845 if (system->flags & KEY_SWITCH_FLAG) {
00846 keyDel(system);
00847 system=0;
00848 } else ksInsert(returned,system);
00849
00850 return returned->size;
00851 }
00852
00853
00854
00873 int kdbStatKey(Key *key) {
00874 int rc=0;
00875
00876 if (backend && backend->kdbStatKey)
00877 rc=backend->kdbStatKey(key);
00878 else {
00879 errno=KDB_RET_NOSYS;
00880 return -1;
00881 }
00882
00883 return rc;
00884 }
00885
00886
00887
00897 int kdbGetKey(Key *key) {
00898 int rc=0;
00899
00900 if (backend && backend->kdbGetKey)
00901 rc=backend->kdbGetKey(key);
00902 else {
00903 errno=KDB_RET_NOSYS;
00904 return -1;
00905 }
00906
00907 return rc;
00908 }
00909
00910
00911
00931 int kdbSetKeys(KeySet *ks) {
00932 int rc=0;
00933
00934 if (backend) {
00935 if(backend->kdbSetKeys)
00936 rc=backend->kdbSetKeys(ks);
00937 else
00938
00939 rc=kdbSetKeys_default(ks);
00940 }
00941 else {
00942 errno=KDB_RET_NOSYS;
00943 return -1;
00944 }
00945
00946 return rc;
00947 }
00948
00949
00950
00961 int kdbSetKeys_default(KeySet *ks) {
00962 Key *current=ksCurrent(ks);
00963 int ret;
00964
00965 if (!current) current=ksNext(ks);
00966 while (current) {
00967 if (keyNeedsSync(current))
00968 if ((ret=kdbSetKey(current)))
00969 return ret;
00970
00971 current=ksNext(ks);
00972 }
00973
00974 return 0;
00975 }
00976
00977
00978
00987 int kdbSetKey(Key *key) {
00988 int rc=0;
00989
00990 if (backend && backend->kdbSetKey)
00991 rc=backend->kdbSetKey(key);
00992 else {
00993 errno=KDB_RET_NOSYS;
00994 return -1;
00995 }
00996
00997 return rc;
00998 }
00999
01000
01001
01002
01012 int kdbRename(Key *key, const char *newName) {
01013 int rc=0;
01014
01015 if (backend && backend->kdbRename)
01016 rc=backend->kdbRename(key,newName);
01017 else {
01018 errno=KDB_RET_NOSYS;
01019 return -1;
01020 }
01021
01022 return rc;
01023 }
01024
01025
01026
01040 int kdbRemoveKey(const Key *key) {
01041 int rc=0;
01042
01043 if (backend && backend->kdbRemoveKey)
01044 rc=backend->kdbRemoveKey(key);
01045 else {
01046 errno=KDB_RET_NOSYS;
01047 return -1;
01048 }
01049
01050 return rc;
01051 }
01052
01053
01054
01065 int kdbRemove(const char *keyName) {
01066 int rc=0;
01067 Key *key=0;
01068
01069 key=keyNew(KEY_SWITCH_END);
01070 rc=keySetName(key,keyName);
01071 if (rc == 0) {
01072 keyDel(key);
01073 return -1;
01074 }
01075
01076 rc=kdbRemoveKey(key);
01077 keyDel(key);
01078
01079 return rc;
01080 }
01081
01082
01083
01084
01085
01097 int kdbLink(const char *oldPath, const char *newKeyName) {
01098 Key *key;
01099 int rc;
01100
01101 key=keyNew(newKeyName,KEY_SWITCH_END);
01102 keySetLink(key,oldPath);
01103
01104 rc=kdbSetKey(key);
01105 keyDel(key);
01106
01107 return rc;
01108 }
01109
01110
01111
01112
01171 uint32_t kdbMonitorKeys(KeySet *interests, uint32_t diffMask,
01172 unsigned long iterations, unsigned sleep) {
01173
01174 uint32_t rc=0;
01175
01176 if (backend) {
01177 if(backend->kdbMonitorKeys)
01178 rc=backend->kdbMonitorKeys(interests,diffMask,iterations,sleep);
01179 else
01180
01181 rc = kdbMonitorKeys_default(interests,diffMask,iterations,sleep);
01182 }
01183 else {
01184 errno=KDB_RET_NOSYS;
01185 return 0;
01186 }
01187
01188 return rc;
01189 }
01190
01191
01199 uint32_t kdbMonitorKeys_default(KeySet *interests, uint32_t diffMask,
01200 unsigned long iterations, unsigned sleeptime) {
01201 Key *start,*current;
01202 uint32_t diff;
01203 int infinitum=0;
01204
01205 if (!interests || !interests->size) return 0;
01206
01207
01208 if (!sleeptime) sleeptime=1000;
01209
01210 if (!iterations) infinitum=1;
01211 else infinitum=0;
01212
01213 current=start=ksCurrent(interests);
01214
01215 while (infinitum || --iterations) {
01216 do {
01217 diff=kdbMonitorKey(current,diffMask,1,0);
01218 if (diff) return diff;
01219 current=ksNext(interests);
01220 } while (current!=start);
01221
01222
01223 if (infinitum || iterations) usleep(sleeptime);
01224 }
01225 return 0;
01226 }
01227
01228
01229
01269 uint32_t kdbMonitorKey(Key *interest, uint32_t diffMask,
01270 unsigned long iterations, unsigned sleep) {
01271
01272 int rc=0;
01273
01274 if (backend) {
01275 if(backend->kdbMonitorKey)
01276 rc=backend->kdbMonitorKey(interest,diffMask,iterations,sleep);
01277 else
01278 rc=kdbMonitorKey_default(interest,diffMask,iterations,sleep);
01279 }
01280 else {
01281 errno=KDB_RET_NOSYS;
01282 return 0;
01283 }
01284
01285 return rc;
01286 }
01287
01288
01289
01290
01298 uint32_t kdbMonitorKey_default(Key *interest, uint32_t diffMask,
01299 unsigned long iterations, unsigned sleeptime) {
01300 Key *tested;
01301 int rc;
01302 uint32_t diff;
01303 int infinitum=0;
01304
01305
01306 if (!interest || !keyGetNameSize(interest)) return 0;
01307
01308
01309 if (!sleeptime) sleeptime=1000;
01310
01311 if (!iterations) infinitum=1;
01312 else infinitum=0;
01313
01314
01315 tested=keyNew(0);
01316 keyDup(interest,tested);
01317
01318 while (infinitum || --iterations) {
01319 rc=kdbGetKey(tested);
01320 if (rc) {
01321
01322 switch (errno) {
01323 case KDB_RET_NOCRED:
01324 keyDel(tested);
01325 return KEY_SWITCH_NEEDSYNC;
01326 case KDB_RET_NOTFOUND:
01327 keyDel(tested);
01328 return KEY_SWITCH_FLAG;
01329 }
01330 }
01331
01332 diff=keyCompare(tested,interest);
01333
01334 if (diff & diffMask) {
01335
01336
01337
01338
01339 keyDup(tested,interest);
01340 keyDel(tested);
01341 return diff;
01342 }
01343
01344 if (infinitum || iterations) usleep(sleeptime);
01345 }
01346
01347 keyDel(tested);
01348
01349 return 0;
01350 }
01351
01352
01353
01425 KDBBackend *kdbBackendExport(const char *backendName, ...) {
01426 va_list va;
01427 KDBBackend *returned;
01428 uint32_t method=0;
01429
01430 if (backendName == 0) return 0;
01431
01432 returned=malloc(sizeof(KDBBackend));
01433 memset(returned,0,sizeof(KDBBackend));
01434
01435 returned->name=(char *)malloc(strblen(backendName));
01436 strcpy(returned->name,backendName);
01437
01438
01439
01440 va_start(va,backendName);
01441
01442 while ((method=va_arg(va,uint32_t))) {
01443 switch (method) {
01444 case KDB_BE_OPEN:
01445 returned->kdbOpen=va_arg(va,kdbOpenPtr);
01446 break;
01447 case KDB_BE_CLOSE:
01448 returned->kdbClose=va_arg(va,kdbClosePtr);
01449 break;
01450 case KDB_BE_STATKEY:
01451 returned->kdbStatKey=va_arg(va,kdbStatKeyPtr);
01452 break;
01453 case KDB_BE_GETKEY:
01454 returned->kdbGetKey=va_arg(va,kdbGetKeyPtr);
01455 break;
01456 case KDB_BE_SETKEY:
01457 returned->kdbSetKey=va_arg(va,kdbSetKeyPtr);
01458 break;
01459 case KDB_BE_RENAME:
01460 returned->kdbRename=va_arg(va,kdbRenamePtr);
01461 break;
01462 case KDB_BE_REMOVEKEY:
01463 returned->kdbRemoveKey=va_arg(va,kdbRemoveKeyPtr);
01464 break;
01465 case KDB_BE_GETCHILD:
01466 returned->kdbGetKeyChildKeys=
01467 va_arg(va,kdbGetChildKeysPtr);
01468 break;
01469 case KDB_BE_SETKEYS:
01470 returned->kdbSetKeys=va_arg(va,kdbSetKeysPtr);
01471 break;
01472 case KDB_BE_MONITORKEY:
01473 returned->kdbMonitorKey=
01474 va_arg(va,kdbMonitorKeyPtr);
01475 break;
01476 case KDB_BE_MONITORKEYS:
01477 returned->kdbMonitorKeys=
01478 va_arg(va,kdbMonitorKeysPtr);
01479 break;
01480 }
01481 }
01482 va_end(va);
01483
01484 return returned;
01485 }
01486
01513 KDBInfo *kdbGetInfo(void) {
01514 KDBInfo *info=0;
01515
01516 info=malloc(sizeof(struct _KDBInfo));
01517 memset(info,0,sizeof(struct _KDBInfo));
01518
01519 #ifdef HAVE_CONFIG_H
01520 info->version=VERSION;
01521 #endif
01522
01523 if (backend) {
01524 info->backendName=backend->name;
01525 info->backendIsOpen=1;
01526 } else {
01527 info->backendName=getenv("KDB_BACKEND");
01528 if (!info->backendName) info->backendName="default";
01529
01530 info->backendIsOpen=0;
01531 }
01532
01533 return info;
01534 }
01535
01536
01537
01548 void kdbFreeInfo(KDBInfo *info) {
01549 free(info);
01550 info=0;
01551 }
01552
01553
01581 int kdbInfoToString(KDBInfo *info,char *string,size_t maxSize) {
01582 if (!info) {
01583 strncpy(string,"No info",maxSize);
01584 return -1;
01585 }
01586
01587 snprintf(string,maxSize,
01588 "Elektra version: %s\nBackend name: %s\nBackend open: %s",
01589 info->version,
01590 info->backendName,
01591 info->backendIsOpen?"yes":"no");
01592
01593 return 0;
01594 }
01595