00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <errno.h>
00029 #include <string.h>
00030 #ifdef HAVE_LANGINFO_H
00031 #include <langinfo.h>
00032 #endif
00033
00034 #include "kdb.h"
00035 #include "kdbprivate.h"
00036
00070 KeySet *ksNew() {
00071 KeySet *new=(KeySet *)malloc(sizeof(KeySet));
00072 ksInit(new);
00073 return new;
00074 }
00075
00076
00077
00089 int ksDel(KeySet *ks) {
00090 int rc;
00091
00092 rc=ksClose(ks);
00093 free(ks);
00094
00095 return rc;
00096 }
00097
00098
00099
00103 ssize_t ksGetSize(KeySet *ks) {
00104 return ks->size;
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00127 int ksRewind(KeySet *ks) {
00128 ks->cursor=0;
00129 return 0;
00130 }
00131
00132
00133
00147 Key *ksNext(KeySet *ks) {
00148 if (ks->cursor) ks->cursor=ks->cursor->next;
00149 else ks->cursor=ks->start;
00150
00151 return ks->cursor;
00152 }
00153
00154
00155
00163 Key *ksCurrent(const KeySet *ks) {
00164 return ks->cursor;
00165 }
00166
00167
00168
00176 Key *ksHead(KeySet *ks) {
00177 return ks->start;
00178 }
00179
00180
00181
00188 Key *ksTail(KeySet *ks) {
00189 return ks->end;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00247 Key *ksLookupByName(KeySet *ks, const char *name, unsigned long options) {
00248 Key *init=0;
00249 Key *current=0;
00250 size_t nameSize;
00251 size_t currentNameSize;
00252 char * keyname;
00253
00254 nameSize=strblen(name);
00255
00256 init=ks->cursor;
00257
00258 while ((current=ksNext(ks))) {
00259 if (current->key == name) return current;
00260
00261
00266 if (name [0] == '/') {
00267 keyname = strchr(current->key, '/');
00268 } else {
00269 keyname = keyStealName (current);
00270 }
00271
00272 #ifdef VERBOSE
00273 fprintf (stderr, "Compare %s with %s\n", keyname, name);
00274 #endif
00275
00276 if ((current->key && name)) {
00277 if ((options & KDB_O_NOCASE) &&
00278 !strcasecmp(keyname,name)) return current;
00279 else if (!strcmp(keyname,name)) return current;
00280 }
00281 }
00282
00283
00284 ks->cursor=init;
00285
00286 return 0;
00287 }
00288
00289
00290
00378 uint32_t ksLookupRE(KeySet *ks, uint32_t where,
00379 const regex_t *regexp, unsigned long options) {
00380 #ifdef HAVE_REGEX_H
00381 regmatch_t offsets;
00382 uint32_t match=0;
00383 Key *init, *walker;
00384 char *parentName=0;
00385 size_t walkerNameSize=0,parentNameSize=0;
00386
00387 init=ks->cursor;
00388 if (!init)
00389
00390 options &= options & ~KDB_O_NOSPANPARENT;
00391
00392 if (options & KDB_O_NOSPANPARENT) {
00393
00394 parentNameSize=keyGetParentNameSize(init);
00395 parentName=(char *)malloc(parentNameSize);
00396 keyGetParentName(init,parentName,parentNameSize);
00397 }
00398
00399 while ((walker=ksNext(ks))) {
00400 walkerNameSize=keyGetNameSize(walker);
00401
00402 if (options & KDB_O_NOSPANPARENT) {
00403
00404 if (walkerNameSize < parentNameSize)
00405
00406 break;
00407
00408 if (memcmp(parentName,walker->key,parentNameSize))
00409
00410 break;
00411 }
00412
00413 if ((where & KEY_SWITCH_NAME) && walker->key)
00414 if (!regexec(regexp,walker->key,1,&offsets,0))
00415 match |= KEY_SWITCH_NAME;
00416
00417 if ((where & KEY_SWITCH_VALUE) && walker->data &&
00418 !(KEY_TYPE_BINARY <= walker->type && walker->type < KEY_TYPE_STRING))
00419 if (!regexec(regexp,(char *)walker->data,1,&offsets,0))
00420 match |= KEY_SWITCH_VALUE;
00421
00422 if ((where & KEY_SWITCH_OWNER) && keyIsUser(walker))
00423 if (!regexec(regexp,walker->userDomain,1,&offsets,0))
00424 match |= KEY_SWITCH_OWNER;
00425
00426 if ((where & KEY_SWITCH_COMMENT) && walker->comment)
00427 if (!regexec(regexp,walker->comment,1,&offsets,0))
00428 match |= KEY_SWITCH_OWNER;
00429
00430 if (match) return match;
00431 }
00432
00433 if (parentName) free(parentName);
00434 ks->cursor=init;
00435 #endif
00436 return 0;
00437 }
00438
00439
00470 Key *ksLookupByValue(KeySet *ks, const char *value, unsigned long options) {
00471 Key *init=0;
00472 Key *current=0;
00473 size_t size=0;
00474
00475 size=strblen(value);
00476 init=ks->cursor;
00477
00478 while ((current=ksNext(ks))) {
00479 if (current->data == value) return current;
00480
00481 if (size != current->dataSize) continue;
00482
00483 if (KEY_TYPE_BINARY<= current->type && current->type < KEY_TYPE_STRING)
00484 continue;
00485
00486 if ((current->data && value)) {
00487 if ((options & KDB_O_NOCASE) &&
00488 !strcasecmp(current->data,value)) return current;
00489 else if (!strcmp(current->data,value)) return current;
00490 }
00491 }
00492
00493
00494 ks->cursor=init;
00495
00496 return 0;
00497 }
00498
00499
00500
00519 Key *ksLookupByBinaryValue(KeySet *ks, void *value, size_t size,
00520 unsigned long options) {
00521 Key *init=0;
00522 Key *current=0;
00523
00524 init=ks->cursor;
00525
00526 while ((current=ksNext(ks))) {
00527 if (current->data == value) return current;
00528
00529 if (size != current->dataSize) continue;
00530
00531 if ((current->data && value) &&
00532 !memcmp(current->data,value,size)) return current;
00533 }
00534
00535
00536 ks->cursor=init;
00537
00538 return 0;
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00566 ssize_t ksInsert(KeySet *ks, Key *toInsert) {
00567 toInsert->next=ks->start;
00568 ks->start=toInsert;
00569 if (!ks->end) ks->end=toInsert;
00570 return ++ks->size;
00571 }
00572
00573
00586 Key *ksPop(KeySet *ks) {
00587 Key *key=0;
00588
00589 if (ks->start) {
00590 key=ks->start;
00591 ks->start=key->next;
00592 if (ks->end == key) ks->end=0;
00593 ks->size--;
00594 if (ks->cursor == key) ks->cursor=0;
00595 }
00596
00597 return key;
00598 }
00599
00600
00613 Key *ksPopLast(KeySet *ks) {
00614 Key *key=0;
00615 Key *prev=0;
00616
00617
00618 if (ks->end == 0) return 0;
00619
00620
00621 if (ks->start == ks->end) {
00622 key=ks->end;
00623 ks->cursor=ks->start=ks->end=0;
00624 ks->size=0;
00625
00626 return key;
00627 }
00628
00629 prev=ks->start;
00630 while (prev->next!=ks->end) prev=prev->next;
00631
00632 key=ks->end;
00633 prev->next=0;
00634 ks->end=prev;
00635 ks->size--;
00636 if (ks->cursor == key) ks->cursor=0;
00637
00638 return key;
00639 }
00640
00641
00653 ssize_t ksInsertKeys(KeySet *ks, KeySet *toInsert) {
00654 if (toInsert->size) {
00655 toInsert->end->next=ks->start;
00656 ks->start=toInsert->start;
00657
00658 ks->size+=toInsert->size;
00659
00660
00661 toInsert->start=toInsert->end=toInsert->cursor=0;
00662 toInsert->size=0;
00663 }
00664 return ks->size;
00665 }
00666
00667
00668
00683 ssize_t ksAppend(KeySet *ks, Key *toAppend) {
00684 toAppend->next=0;
00685 if (ks->end) ks->end->next=toAppend;
00686 if (!ks->start) ks->start=toAppend;
00687 ks->end=toAppend;
00688 return ++ks->size;
00689 }
00690
00691
00692
00705 ssize_t ksAppendKeys(KeySet *ks, KeySet *toAppend) {
00706 if (toAppend->size) {
00707 if (ks->end) {
00708 ks->end->next=toAppend->start;
00709 ks->end=toAppend->end;
00710 } else {
00711 ks->end=toAppend->end;
00712 ks->start=toAppend->start;
00713 }
00714
00715 ks->size+=toAppend->size;
00716
00717
00718 toAppend->start=toAppend->end=toAppend->cursor=0;
00719 toAppend->size=0;
00720 }
00721 return ks->size;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00798 int ksCompare(KeySet *ks1, KeySet *ks2, KeySet *removed) {
00799 int flagRemoved=1;
00800 Key *ks1Cursor=0;
00801 Key *ks2Cursor=0;
00802
00803 Key *ks1PrevCursor=0;
00804
00805 ks1Cursor=ks1->start;
00806 while (ks1Cursor) {
00807 Key *ks2PrevCursor=0;
00808 flagRemoved=1;
00809
00810 for (ks2Cursor=ks2->start; ks2Cursor; ks2Cursor=ks2Cursor->next) {
00811 uint32_t flags=keyCompare(ks1Cursor,ks2Cursor);
00812
00813 if (!(flags & (KEY_SWITCH_NAME | KEY_SWITCH_DOMAIN))) {
00814
00815 flagRemoved=0;
00816
00817
00818 if (ks2PrevCursor) ks2PrevCursor->next=ks2Cursor->next;
00819 else ks2->start=ks2Cursor->next;
00820 if (ks2->end==ks2Cursor) ks2->end=ks2PrevCursor;
00821 ks2->size--;
00822
00823 if (flags) {
00824
00825
00826
00827 if (ks1PrevCursor) ks1PrevCursor->next=ks2Cursor;
00828 else ks1->start=ks2Cursor;
00829 if (ks1->end==ks1Cursor) ks1->end=ks2Cursor;
00830 ks2Cursor->next=ks1Cursor->next;
00831
00832
00833 keyDel(ks1Cursor);
00834
00835
00836 ks1Cursor=ks2Cursor;
00837 } else {
00838
00839
00840
00841 keyDel(ks2Cursor);
00842 }
00843
00844 break;
00845 }
00846 ks2PrevCursor=ks2Cursor;
00847
00848 }
00849
00850 if (flagRemoved) {
00851
00852
00853
00854
00855 if (ks1PrevCursor) ks1PrevCursor->next=ks1Cursor->next;
00856 else ks1->start=ks1Cursor->next;
00857 if (ks1->end==ks1Cursor) ks1->end=ks1PrevCursor;
00858 ks1->size--;
00859
00860
00861 ksAppend(removed,ks1Cursor);
00862
00863
00864 if (ks1PrevCursor) ks1Cursor=ks1PrevCursor->next;
00865 else ks1Cursor=ks1->start;
00866 } else {
00867 ks1PrevCursor=ks1Cursor;
00868 ks1Cursor=ks1Cursor->next;
00869 }
00870 }
00871
00872
00873 ksAppendKeys(ks1,ks2);
00874
00875 return 0;
00876 }
00877
00878
00879
00880
00942 ssize_t ksToStream(const KeySet *ks, FILE* stream, unsigned long options) {
00943 size_t written=0;
00944 Key *key=0;
00945 char *codeset;
00946
00947
00948
00949 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
00950 codeset = nl_langinfo(CODESET);
00951 #else
00952 codeset = "UTF-8";
00953 #endif
00954 if (options & KDB_O_XMLHEADERS) {
00955 written+=fprintf(stream,"<?xml version=\"1.0\" encoding=\"%s\"?>\n",
00956 codeset);
00957 written+=fprintf(stream,
00958 "\n\n<!-- Generated by Elektra API. Total of %d keys. -->\n\n\n\n",ks->size);
00959
00960 written+=fprintf(stream,"<keyset xmlns=\"http://www.libelektra.org\"\n\
00961 xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\
00962 xsi:schemaLocation=\"http://www.libelektra.org elektra.xsd\"");
00963
00964
00965
00966 } else written+=fprintf(stream,"<keyset");
00967
00968 if (options & KDB_O_HIER) {
00969 Key *smalest=0;
00970 size_t ssmalest=0;
00971
00972 for (key=ks->start; key; key=key->next) {
00973 if (smalest) {
00974 size_t size=strblen(key->key);
00975 if (size<ssmalest) {
00976 smalest=key;
00977 ssmalest=size;
00978 }
00979 } else {
00980 smalest=key;
00981 ssmalest=strblen(smalest->key);
00982 }
00983 }
00984
00985 if (keyIsUser(smalest) && (options & KDB_O_FULLNAME)) {
00986 char buffer[800];
00987 keyGetFullName(smalest,buffer,sizeof(buffer));
00988 written+=fprintf(stream,"\n\n parent=\"%s\"",buffer);
00989 } else
00990 written+=fprintf(stream,"\n\n parent=\"%s\"",smalest->key);
00991
00992 written+=fprintf(stream,">\n\n\n");
00993
00994 for (key=ks->start; key; key=key->next)
00995 written+=keyToStreamBasename(key,stream,smalest->key,0,options);
00996 } else {
00997 written+=fprintf(stream,">\n\n\n");
00998 for (key=ks->start; key; key=key->next)
00999 written+=keyToStream(key,stream,options);
01000 }
01001
01002 written+=fprintf(stream,"</keyset>\n");
01003 return written;
01004 }
01005
01006
01007
01008
01009 int keyCompareByName(const void *p1, const void *p2) {
01010 Key *key1=*(Key **)p1;
01011 Key *key2=*(Key **)p2;
01012
01013 return strcmp(key1->key, key2->key);
01014 }
01015
01016
01022 void ksSort(KeySet *ks) {
01023 Key **keys = NULL;
01024 Key *cursor;
01025 size_t c=0;
01026
01027 if (ks->size) {
01028 keys = (Key **)calloc(ks->size, sizeof(Key *));
01029
01030 for (cursor=ks->start; cursor; cursor=cursor->next, c++)
01031 keys[c]=cursor;
01032
01033 qsort(keys,ks->size,sizeof(Key *),keyCompareByName);
01034
01035 ks->start=cursor=keys[0];
01036 for (c=1; c<ks->size; c++) {
01037 cursor->next=keys[c];
01038 cursor=cursor->next;
01039 }
01040 cursor->next=0;
01041 ks->end=cursor;
01042 free(keys);
01043 }
01044 }
01045
01046
01047
01048
01049
01050
01063 int ksInit(KeySet *ks) {
01064 ks->start=ks->end=ks->cursor=0;
01065 ks->size=0;
01066
01067 return 0;
01068 }
01069
01070
01082 int ksClose(KeySet *ks) {
01083 if (ks->size) {
01084 while (ks->size) {
01085 Key *destroyer=ks->start;
01086 ks->start=destroyer->next;
01087 keyDel(destroyer);
01088 --ks->size;
01089 }
01090 }
01091 ks->cursor=ks->end=ks->start;
01092 return 0;
01093 }
01094
01095
01096
01097
01098
01099