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 #include <stdio.h>
00026 #include <strings.h>
00027 #include <string.h>
00028 #include <stdlib.h>
00029 #include <sys/stat.h>
00030 #include <errno.h>
00031 #include <unistd.h>
00032 #include <sys/types.h>
00033 #include <pwd.h>
00034 #include <grp.h>
00035 #include <langinfo.h>
00036
00037 #include "kdb.h"
00038 #include "kdbprivate.h"
00039
00040 extern int errno;
00041
00042
00046 size_t strblen(const char *s) {
00047 char *found=index(s,0);
00048 if (found) return found-s+1;
00049 return 0;
00050 }
00051
00052
00123 int keyInit(Key *key) {
00124 if (!key) return errno=KDB_RET_NULLKEY;
00125
00126 memset(key,0,sizeof(Key));
00127 key->type=KEY_TYPE_UNDEFINED;
00128 key->uid=getuid();
00129 key->gid=getgid();
00130 key->access=umask(0); umask(key->access);
00131 key->access=0666 & ~key->access;
00132
00133 key->flags |= KEY_FLAG_INITIALIZED | KEY_FLAG_ACTIVE;
00134
00135 return 0;
00136 }
00137
00138
00139
00140
00149 int keyClose(Key *key) {
00150 if (!key) return errno=KDB_RET_NULLKEY;
00151 if (!keyIsInitialized(key)) return 0;
00152
00153 free(key->key);
00154 free(key->data);
00155 free(key->comment);
00156 free(key->userDomain);
00157 memset(key,0,sizeof(Key));
00158 return 0;
00159 }
00160
00161
00162
00163
00164
00165
00166
00176 int keyIsInitialized(const Key *key) {
00177 if (!key) return 0;
00178 return ((key->flags & KEY_FLAG_INITMASK)==KEY_FLAG_INITIALIZED);
00179 }
00180
00181
00182
00190 int keyNeedsSync(const Key *key) {
00191 if (!key) return 0;
00192 return (key->flags & KEY_FLAG_NEEDSYNC);
00193 }
00194
00195
00196
00205 u_int8_t keyGetType(const Key *key) {
00206 if (!key || !keyIsInitialized(key)) {
00207 errno=KDB_RET_UNINITIALIZED;
00208 return KEY_TYPE_UNDEFINED;
00209 }
00210
00211 return key->type;
00212 }
00213
00214
00278 u_int8_t keySetType(Key *key,u_int8_t newType) {
00279 mode_t dirSwitch=0111;
00280
00281 if (!key) {
00282 errno=KDB_RET_UNINITIALIZED;
00283 return KEY_TYPE_UNDEFINED;
00284 }
00285 if (!keyIsInitialized(key)) keyInit(key);
00286
00287 switch (newType) {
00288 case KEY_TYPE_DIR:
00289 key->type=KEY_TYPE_DIR;
00290 dirSwitch=umask(0); umask(dirSwitch);
00291 dirSwitch=0111 & ~dirSwitch;
00292 key->access|=dirSwitch | S_IFDIR;
00293 keySetRaw(key,0,0);
00294 break;
00295 default:
00296 key->type=newType;
00297 key->access &= ~(S_IFDIR | dirSwitch);
00298 key->flags |= KEY_FLAG_NEEDSYNC;
00299 }
00300 return key->type;
00301 }
00302
00303
00304
00314 size_t keyGetDataSize(const Key *key) {
00315 if (!key || !keyIsInitialized(key)) {
00316 errno=KDB_RET_UNINITIALIZED;
00317 return -1;
00318 }
00319
00320 return key->dataSize;
00321 }
00322
00323
00324 size_t keyGetRecordSize(const Key *key) {
00325 if (!key || !keyIsInitialized(key)) {
00326 errno=KDB_RET_UNINITIALIZED;
00327 return -1;
00328 }
00329
00330 return key->recordSize;
00331 }
00332
00333
00334
00335
00343 size_t keyGetNameSize(const Key *key) {
00344 if (!key || !keyIsInitialized(key)) {
00345 errno=KDB_RET_UNINITIALIZED;
00346 return 0;
00347 }
00348
00349 if (key->key) return strblen(key->key);
00350 else return 0;
00351 }
00352
00353
00354
00355
00363 size_t keyGetFullNameSize(const Key *key) {
00364 size_t returnedSize;
00365
00366 if (!key || !keyIsInitialized(key)) {
00367 errno=KDB_RET_UNINITIALIZED;
00368 return -1;
00369 }
00370
00371 if (!key->key) return 0;
00372
00373 returnedSize=strblen(key->key);
00374
00375 if (!strncmp("user",key->key,sizeof("user")-1) && key->userDomain)
00376 returnedSize+=strblen(key->userDomain);
00377
00378 return returnedSize;
00379 }
00380
00381
00382
00391 size_t keyGetFullName(const Key *key, char *returnedName, size_t maxSize) {
00392 size_t userSize=sizeof("user")-1;
00393 size_t userDomainSize,length;
00394 char *cursor;
00395
00396 length=keyGetFullNameSize(key);
00397 if (length < 0) return length;
00398 if (length > maxSize) {
00399 errno=KDB_RET_TRUNC;
00400 return -1;
00401 }
00402
00403 cursor=returnedName;
00404 if (!strncmp("user",key->key,userSize)) {
00405 strncpy(cursor,key->key,userSize);
00406 cursor+=userSize;
00407 if (key->userDomain) {
00408 *cursor=':'; ++cursor;
00409 userDomainSize=strblen(key->userDomain)-1;
00410 strcpy(cursor,key->userDomain);
00411 cursor+=userDomainSize;
00412 }
00413 strcpy(cursor,key->key+userSize);
00414 } else strcpy(cursor,key->key);
00415
00416 return length;
00417 }
00418
00419
00420
00421
00430 size_t keyGetName(const Key *key, char *returnedName, size_t maxSize) {
00431 size_t bytes;
00432
00433 if (!key || !keyIsInitialized(key)) {
00434 errno=KDB_RET_UNINITIALIZED;
00435 return 0;
00436 }
00437
00438 if (!key->key) {
00439 errno=KDB_RET_NOKEY;
00440 return 0;
00441 }
00442
00443 bytes=strblen(strncpy(returnedName,key->key,maxSize));
00444 if (maxSize < strblen(key->key)) {
00445 errno=KDB_RET_TRUNC;
00446 return 0;
00447 }
00448 return bytes;
00449 }
00450
00451
00452
00453
00454
00477 size_t keySetName(Key *key, const char *newName) {
00478 size_t length;
00479 size_t rootLength, userLength, systemLength, userDomainLength;
00480 size_t keyNameSize=1;
00481
00482 if (!key) {
00483 errno=KDB_RET_UNINITIALIZED;
00484 return 0;
00485 }
00486 if (!keyIsInitialized(key)) keyInit(key);
00487
00488
00489 if (!newName || !(length=strlen(newName))) {
00490 if (key->key) {
00491 free(key->key);
00492 key->key=0;
00493 }
00494 key->flags &= ~(KEY_FLAG_HASKEY | KEY_FLAG_NEEDSYNC);
00495 return 0;
00496 }
00497
00498
00499 while (newName[length]==RG_KEY_DELIM) {
00500 length--;
00501 }
00502
00503 rootLength=keyNameGetRootNameSize(newName);
00504 if (!rootLength) {
00505 errno=KDB_RET_INVALIDKEY;
00506 return 0;
00507 }
00508 userLength=sizeof("user")-1;
00509 systemLength=sizeof("system")-1;
00510 userDomainLength=rootLength-userLength-1;
00511 if (userDomainLength<0) userDomainLength=0;
00512
00513 if (!strncmp("user",newName,userLength<length?userLength:length)) {
00514
00515 if (length > userLength) {
00516
00517 if (*(newName+userLength)==':') {
00518
00519 if (userDomainLength > 0) {
00520 key->userDomain=realloc(key->userDomain,userDomainLength+1);
00521 strncpy(key->userDomain,newName+userLength+1,userDomainLength);
00522 key->userDomain[userDomainLength]=0;
00523 }
00524 keyNameSize+=length-userDomainLength-1;
00525 } else if (*(newName+userLength)!=RG_KEY_DELIM) {
00526
00527 errno=KDB_RET_INVALIDKEY;
00528 return 0;
00529 } else {
00530
00531 keyNameSize+=length;
00532 }
00533 } else {
00534
00535 keyNameSize+=userLength;
00536 }
00537
00538 key->key=realloc(key->key,keyNameSize);
00539
00540
00541 if (!key->key) return 0;
00542
00543 strcpy(key->key,"user");
00544 strncpy(key->key+userLength,newName+rootLength,length-rootLength);
00545 key->key[keyNameSize-1]=0;
00546
00547 if (!key->userDomain) {
00548 size_t bsize=strblen(getenv("USER"));
00549
00550 if (!bsize) {}
00551 else {
00552 key->userDomain=malloc(bsize);
00553 strncpy(key->userDomain,getenv("USER"),bsize);
00554 }
00555 }
00556
00557 } else if (!strncmp("system",newName,systemLength<length?systemLength:length)) {
00558
00559 if (length > systemLength && *(newName+systemLength)!=RG_KEY_DELIM) {
00560
00561 errno=KDB_RET_INVALIDKEY;
00562 return 0;
00563 }
00564 keyNameSize+=length;
00565 key->key=realloc(key->key,keyNameSize);
00566
00567
00568 if (!key->key) return 0;
00569
00570 strncpy(key->key,newName,length);
00571 key->key[keyNameSize-1]=0;
00572 } else {
00573
00574 errno=KDB_RET_INVALIDKEY;
00575 return 0;
00576 }
00577
00578 key->flags |= KEY_FLAG_HASKEY | KEY_FLAG_NEEDSYNC;
00579
00580 return keyNameSize;
00581 }
00582
00583
00584
00606 size_t keyGetOwner(const Key *key, char *returned, size_t maxSize) {
00607 size_t bytes;
00608
00609 if (!key || !keyIsInitialized(key)) {
00610 errno=KDB_RET_UNINITIALIZED;
00611 return 0;
00612 }
00613
00614 if (!key->userDomain) {
00615 errno=KDB_RET_NODOMAIN;
00616 return 0;
00617 }
00618
00619 if (maxSize < (bytes=strblen(key->userDomain))) {
00620 errno=KDB_RET_TRUNC;
00621 return 0;
00622 } else strcpy(returned,key->userDomain);
00623 return bytes;
00624 }
00625
00632 size_t keyGetOwnerSize(const Key *key) {
00633
00634 if (!key || !keyIsInitialized(key)) {
00635 errno=KDB_RET_UNINITIALIZED;
00636 return 0;
00637 }
00638
00639 if (!key->userDomain) {
00640 errno=KDB_RET_NODOMAIN;
00641 return 0;
00642 }
00643
00644 return strblen(key->userDomain);
00645 }
00646
00647
00660 size_t keySetOwner(Key *key, const char *userDomain) {
00661 size_t size;
00662
00663 if (!key) {
00664 errno=KDB_RET_UNINITIALIZED;
00665 return -1;
00666 }
00667 if (!keyIsInitialized(key)) keyInit(key);
00668
00669 if ((size=strblen(userDomain)) > 0) {
00670 if (key->userDomain) {
00671 key->userDomain=realloc(key->userDomain,size);
00672 } else {
00673 key->userDomain=malloc(size);
00674 }
00675 if (!key->userDomain) return -1;
00676
00677 strcpy(key->userDomain,userDomain);
00678 key->flags |= KEY_FLAG_HASDOMAIN | KEY_FLAG_NEEDSYNC;
00679 return size;
00680 } else if (key->userDomain) {
00681 free(key->userDomain);
00682 key->userDomain=0;
00683 key->flags &= ~(KEY_FLAG_HASDOMAIN | KEY_FLAG_NEEDSYNC);
00684 }
00685 return 0;
00686 }
00687
00688
00689
00690
00702 size_t keyGetComment(const Key *key, char *returnedDesc, size_t maxSize) {
00703 size_t bytes;
00704
00705 if (!key || !keyIsInitialized(key)) {
00706 errno=KDB_RET_UNINITIALIZED;
00707 return 0;
00708 }
00709
00710 if (!key->comment) {
00711 errno=KDB_RET_NODESC;
00712 return 0;
00713 }
00714
00715 bytes=strblen(strncpy(returnedDesc,key->comment,maxSize));
00716 if (maxSize < strblen(key->comment)) {
00717 errno=KDB_RET_TRUNC;
00718 return 0;
00719 }
00720 return bytes;
00721 }
00722
00723
00724
00735 size_t keySetComment(Key *key, const char *newComment) {
00736 size_t size;
00737
00738 if (!key) {
00739 errno=KDB_RET_UNINITIALIZED;
00740 return 0;
00741 }
00742 if (!keyIsInitialized(key)) keyInit(key);
00743
00744 if (newComment && (size=strblen(newComment)) > 0) {
00745 if (key->flags & KEY_FLAG_HASCOMMENT) {
00746 key->comment=realloc(key->comment,size);
00747 } else {
00748 key->comment=malloc(size);
00749 }
00750 if (!key->comment) return 0;
00751
00752 strcpy(key->comment,newComment);
00753 key->flags |= KEY_FLAG_HASCOMMENT | KEY_FLAG_NEEDSYNC;
00754 return key->commentSize=size;
00755 } else if (key->flags & KEY_FLAG_HASCOMMENT) {
00756 free(key->comment);
00757 key->comment=0;
00758 key->flags &= ~(KEY_FLAG_HASCOMMENT | KEY_FLAG_NEEDSYNC);
00759 }
00760 return key->commentSize=0;
00761 }
00762
00763
00764
00775 size_t keyGetCommentSize(const Key *key) {
00776 if (!key || !keyIsInitialized(key)) {
00777 errno=KDB_RET_UNINITIALIZED;
00778 return 0;
00779 }
00780
00781 if (!key->comment) {
00782 errno=KDB_RET_NODESC;
00783 return 0;
00784 }
00785
00786 return strblen(key->comment);
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00891 size_t keyGetString(const Key *key, char *returnedString, size_t maxSize) {
00892 if (!key || !keyIsInitialized(key)) {
00893 errno=KDB_RET_UNINITIALIZED;
00894 return 0;
00895 }
00896
00897 if (!key->data) {
00898 *returnedString=0;
00899 errno=KDB_RET_NODATA;
00900 return 0;
00901 }
00902
00903 if (key->dataSize > maxSize) {
00904 errno=KDB_RET_TRUNC;
00905 return 0;
00906 }
00907
00908 if (key->type < KEY_TYPE_STRING) {
00909 errno=KDB_RET_TYPEMISMATCH;
00910 return 0;
00911 }
00912
00913 strcpy(returnedString,key->data);
00914 return key->dataSize;
00915 }
00916
00917
00918
00919
00920
00930 size_t keySetString(Key *key, const char *newString) {
00931 size_t ret=newString?strblen(newString):0;
00932
00933 if (!newString || !ret) ret=keySetRaw(key,0,0);
00934 else keySetRaw(key,newString,ret);
00935
00936 keySetType(key,KEY_TYPE_STRING);
00937
00938 return ret;
00939 }
00940
00941
00942
00943
00953 size_t keyGetBinary(const Key *key, void *returnedBinary, size_t maxSize) {
00954 if (!key || !keyIsInitialized(key))
00955 return errno=KDB_RET_UNINITIALIZED;
00956
00957 if (!key->data) {
00958 errno=KDB_RET_NODATA;
00959 return 0;
00960 }
00961
00962 if (key->dataSize > maxSize) {
00963 errno=KDB_RET_TRUNC;
00964 return 0;
00965 }
00966
00967 memcpy(returnedBinary,key->data,key->dataSize);
00968 return key->dataSize;
00969 }
00970
00971
00972
00973
00990 size_t keySetBinary(Key *key, const void *newBinary, size_t dataSize) {
00991 size_t ret=keySetRaw(key,newBinary,dataSize);
00992
00993 keySetType(key,KEY_TYPE_BINARY);
00994
00995 return ret;
00996 }
00997
00998
00999
01000
01013 size_t keySetRaw(Key *key, const void *newBinary, size_t dataSize) {
01014 if (!key) {
01015 errno=KDB_RET_UNINITIALIZED;
01016 return 0;
01017 }
01018 if (!keyIsInitialized(key)) keyInit(key);
01019
01020 if (!dataSize || !newBinary) {
01021 if (key->data) {
01022 free(key->data);
01023 key->data=0;
01024 }
01025 key->flags &= ~(KEY_FLAG_HASDATA);
01026 key->flags |= KEY_FLAG_NEEDSYNC;
01027 return 0;
01028 }
01029
01030 key->dataSize=dataSize;
01031 if (key->data) key->data=realloc(key->data,key->dataSize);
01032 else key->data=malloc(key->dataSize);
01033
01034 if (!key->data) return 0;
01035
01036 memcpy(key->data,newBinary,key->dataSize);
01037 key->flags |= KEY_FLAG_HASDATA | KEY_FLAG_NEEDSYNC;
01038 return key->dataSize;
01039 }
01040
01041
01042
01043
01044
01045
01046 size_t keyGetLink(const Key *key, char *returnedTarget, size_t maxSize) {
01050 if (!key || !keyIsInitialized(key))
01051 return errno=KDB_RET_UNINITIALIZED;
01052
01053 if (!key->data) {
01054 errno=KDB_RET_NODATA;
01055 return 0;
01056 }
01057
01058 if (key->type != KEY_TYPE_LINK) {
01059 errno=KDB_RET_TYPEMISMATCH;
01060 return 0;
01061 }
01062
01063 if (key->dataSize > maxSize) {
01064 errno=KDB_RET_TRUNC;
01065 return 0;
01066 }
01067
01068 strcpy(returnedTarget,key->data);
01069 return key->dataSize;
01070 }
01071
01072
01073
01074
01075
01076 size_t keySetLink(Key *key, const char *target) {
01077 size_t ret=target?strblen(target):0;
01078
01079 if (!target || !ret) ret=keySetRaw(key,0,0);
01080 else keySetRaw(key,target,ret);
01081
01082 keySetType(key,KEY_TYPE_LINK);
01083
01084 return ret;
01085 }
01086
01087
01088
01103 int keyDup(const Key *source, Key *dest) {
01104
01105
01106 keyClose(dest);
01107
01108
01109 *dest=*source;
01110
01111
01112 dest->key=
01113 dest->comment=
01114 dest->userDomain=
01115 dest->data=0;
01116
01117
01118 keySetName(dest,source->key);
01119 keySetComment(dest,source->comment);
01120 keySetOwner(dest,source->userDomain);
01121 keySetRaw(dest,source->data,source->dataSize);
01122
01123 dest->flags=source->flags;
01124
01125 return 0;
01126 }
01127
01128
01129
01141 uid_t keyGetUID(const Key *key) {
01142 if (!key || !keyIsInitialized(key)) {
01143 errno=KDB_RET_UNINITIALIZED;
01144 return -1;
01145 }
01146
01147
01148
01149 return key->uid;
01150 }
01151
01152
01153
01154
01166 int keySetUID(Key *key, uid_t uid) {
01167 if (!key) return errno=KDB_RET_UNINITIALIZED;
01168 if (!keyIsInitialized(key)) keyInit(key);
01169
01170 key->uid=uid;
01171 key->flags |= KEY_FLAG_HASUID | KEY_FLAG_NEEDSYNC;
01172
01173 return 0;
01174 }
01175
01176
01177
01185 gid_t keyGetGID(const Key *key) {
01186 if (!key || !keyIsInitialized(key)) {
01187 errno=KDB_RET_UNINITIALIZED;
01188 return -1;
01189 }
01190
01191
01192
01193 return key->gid;
01194 }
01195
01196
01197
01205 int keySetGID(Key *key, gid_t gid) {
01206 if (!key) return errno=KDB_RET_UNINITIALIZED;
01207 if (!keyIsInitialized(key)) keyInit(key);
01208
01209 key->gid=gid;
01210 key->flags |= KEY_FLAG_HASGID | KEY_FLAG_NEEDSYNC;
01211
01212 return 0;
01213 }
01214
01215
01216
01221 mode_t keyGetAccess(const Key *key) {
01222 if (!key || !keyIsInitialized(key)) {
01223 errno=KDB_RET_UNINITIALIZED;
01224 return -1;
01225 }
01226
01227
01228
01229 return key->access;
01230 }
01231
01232
01233
01234
01241 int keySetAccess(Key *key, mode_t mode) {
01242 if (!key) return errno=KDB_RET_UNINITIALIZED;
01243 if (!keyIsInitialized(key)) keyInit(key);
01244
01245 key->access=mode;
01246 key->flags |= KEY_FLAG_HASPRM | KEY_FLAG_NEEDSYNC;
01247
01248 return 0;
01249 }
01250
01251
01252
01253
01254
01258 time_t keyGetMTime(const Key *key) {
01259 if (!key || !keyIsInitialized(key)) {
01260 errno=KDB_RET_UNINITIALIZED;
01261 return -1;
01262 }
01263
01264
01265 return key->mtime;
01266 }
01267
01268
01269
01273 time_t keyGetATime(const Key *key) {
01274 if (!key || !keyIsInitialized(key)) {
01275 errno=KDB_RET_UNINITIALIZED;
01276 return -1;
01277 }
01278
01279
01280 return key->atime;
01281 }
01282
01283
01287 time_t keyGetCTime(const Key *key) {
01288 if (!key || !keyIsInitialized(key)) {
01289 errno=KDB_RET_UNINITIALIZED;
01290 return -1;
01291 }
01292
01293
01294 return key->ctime;
01295 }
01296
01297
01298
01303 size_t keyGetParentSize(const Key *key) {
01304 char *parentNameEnd;
01305
01306 if (!key || !keyIsInitialized(key)) {
01307 errno=KDB_RET_UNINITIALIZED;
01308 return 0;
01309 }
01310
01311 if (!key->key) {
01312 errno=KDB_RET_NOKEY;
01313 return 0;
01314 }
01315
01316
01317
01318
01319
01320
01321
01322 parentNameEnd=rindex(key->key,RG_KEY_DELIM);
01323
01324 if (!parentNameEnd || parentNameEnd==key->key) {
01325
01326 return 0;
01327 }
01328
01329
01330 if ((parentNameEnd-key->key) == (strlen(key->key)-1)) {
01331 parentNameEnd--;
01332 while (*parentNameEnd!=RG_KEY_DELIM) parentNameEnd--;
01333 }
01334
01335 return parentNameEnd - key->key;
01336 }
01337
01338
01339
01347 size_t keyGetParent(const Key *key, char *returnedParent, size_t maxSize) {
01348 size_t parentSize;
01349
01350 parentSize=keyGetParentSize(key);
01351
01352 if (parentSize > maxSize) {
01353 errno=KDB_RET_TRUNC;
01354 return 0;
01355 } else strncpy(returnedParent,key->key,parentSize);
01356
01357 return parentSize;
01358 }
01359
01360
01361
01372 u_int32_t keyCompare(const Key *key1, const Key *key2) {
01373 u_int32_t ret=0;
01374
01375
01376
01377 if (key1->uid != key2->uid) ret|=KEY_FLAG_HASUID;
01378 if (key1->gid != key2->gid) ret|=KEY_FLAG_HASGID;
01379 if (key1->type != key2->type) ret|=KEY_FLAG_HASTYPE;
01380 if ((key1->access & (S_IRWXU|S_IRWXG|S_IRWXO)) !=
01381 (key2->access & (S_IRWXU|S_IRWXG|S_IRWXO))) ret|=KEY_FLAG_HASPRM;
01382
01383
01384
01385 if (key1->key && key2->key) {
01386 if (strcmp(key1->key,key2->key)) ret|=KEY_FLAG_HASKEY;
01387 } else {
01388 if (key1->key) ret|=KEY_FLAG_HASKEY;
01389 else if (key2->key) ret|=KEY_FLAG_HASKEY;
01390 }
01391
01392 if (key1->comment && key2->comment) {
01393 if (strcmp(key1->comment,key2->comment)) ret|=KEY_FLAG_HASCOMMENT;
01394 } else {
01395 if (key1->comment) ret|=KEY_FLAG_HASCOMMENT;
01396 else if (key2->comment) ret|=KEY_FLAG_HASCOMMENT;
01397 }
01398
01399 if (key1->userDomain && key2->userDomain) {
01400 if (strcmp(key1->userDomain,key2->userDomain)) ret|=KEY_FLAG_HASDOMAIN;
01401 } else {
01402 if (key1->userDomain) ret|=KEY_FLAG_HASDOMAIN;
01403 else if (key2->comment) ret|=KEY_FLAG_HASDOMAIN;
01404 }
01405
01406
01407
01408 if (memcmp(key1->data,key2->data,
01409 (key1->dataSize<=key2->dataSize?key1->dataSize:key2->dataSize)))
01410 ret|=KEY_FLAG_HASDATA;
01411
01412 return ret;
01413 }
01414
01415
01416
01417
01418
01419
01445 size_t keyToStream(const Key *key, FILE* stream, unsigned long options) {
01446 size_t written=0;
01447 char buffer[800];
01448 struct passwd *pwd=0;
01449 struct group *grp=0;
01450
01451
01452 if (!key || !keyIsInitialized(key) || !key->key) {
01453 errno=KDB_RET_UNINITIALIZED;
01454 return 0;
01455 }
01456
01457 keyGetFullName(key,buffer,sizeof(buffer));
01458
01459 if (!(options & KDB_O_NUMBERS)) {
01460 pwd=getpwuid(keyGetUID(key));
01461 grp=getgrgid(keyGetGID(key));
01462 }
01463
01464
01465 written+=fprintf(stream,"<key name=\"%s\"", buffer);
01466
01467 if (options & KDB_O_CONDENSED) written+=fprintf(stream," ");
01468 else written+=fprintf(stream,"\n ");
01469
01470
01471
01472
01473
01474 if (options & KDB_O_NUMBERS) {
01475 written+=fprintf(stream,"type=\"%d\"", keyGetType(key));
01476 } else {
01477 u_int8_t type=keyGetType(key);
01478 buffer[0]=0;
01479
01480 switch (type) {
01481 case KEY_TYPE_STRING:
01482 strcpy(buffer,"string");
01483 break;
01484 case KEY_TYPE_BINARY:
01485 strcpy(buffer,"binary");
01486 break;
01487 case KEY_TYPE_LINK:
01488 strcpy(buffer,"link");
01489 break;
01490 case KEY_TYPE_DIR:
01491 strcpy(buffer,"directory");
01492 break;
01493 }
01494 if (buffer[0]) written+=fprintf(stream,"type=\"%s\"", buffer);
01495 else written+=fprintf(stream,"type=\"%d\"", type);
01496 }
01497
01498
01499
01500
01501 if (pwd) written+=fprintf(stream," uid=\"%s\"",pwd->pw_name);
01502 else written+=fprintf(stream, " uid=\"%d\"",keyGetUID(key));
01503
01504 if (grp) written+=fprintf(stream," gid=\"%s\"",grp->gr_name);
01505 else written+=fprintf(stream, " gid=\"%d\"",keyGetGID(key));
01506
01507 written+=fprintf(stream," mode=\"0%o\">",
01508 keyGetAccess(key) & (S_IRWXU|S_IRWXG|S_IRWXO));
01509
01510
01511
01512 if (!(options & KDB_O_CONDENSED) && (key->data || key->comment))
01513 written+=fprintf(stream,"\n\n ");
01514
01515 if (key->data)
01516 written+=
01517 fprintf(stream,"<value><![CDATA[%s]]></value>",(char *)key->data);
01518
01519
01520
01521 if (!(options & KDB_O_CONDENSED)) {
01522 written+=fprintf(stream,"\n");
01523 if (key->comment) written+=fprintf(stream," ");
01524 }
01525
01526 if (key->comment) {
01527 written+=fprintf(stream,"<comment><![CDATA[%s]]></comment>", key->comment);
01528 if (!(options & KDB_O_CONDENSED))
01529 written+=fprintf(stream,"\n");
01530 }
01531
01532 written+=fprintf(stream,"</key>");
01533
01534 if (!(options & KDB_O_CONDENSED))
01535 written+=fprintf(stream,"\n\n\n\n\n\n");
01536
01537 return written;
01538 }
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01698 int keyNameIsSystem(const char *keyName) {
01699 if (!keyName) return 0;
01700 if (!strlen(keyName)) return 0;
01701
01702 if (!strncmp("system",keyName,sizeof("system")-1)) return 1;
01703 return 0;
01704 }
01705
01706
01717 int keyNameIsUser(const char *keyName) {
01718 if (!keyName) return 0;
01719 if (!strlen(keyName)) return 0;
01720
01721 if (!strncmp("user",keyName,sizeof("user")-1)) return 1;
01722 return 0;
01723 }
01724
01725
01726
01736 int keyIsSystem(const Key *key) {
01737 if (!key) return 0;
01738 if (!keyIsInitialized(key)) return 0;
01739
01740 return keyNameIsSystem(key->key);
01741 }
01742
01743
01744
01754 int keyIsUser(const Key *key) {
01755 if (!key) return 0;
01756 if (!keyIsInitialized(key)) return 0;
01757
01758 return keyNameIsUser(key->key);
01759 }
01760
01761
01762
01763
01776 int keyNameGetNamespace(const char *keyName) {
01777 if (keyNameIsSystem(keyName)) return KEY_NS_SYSTEM;
01778 if (keyNameIsUser(keyName)) return KEY_NS_USER;
01779 return 0;
01780 }
01781
01782
01783
01796 int keyGetNamespace(const Key *key) {
01797 if (!key) return 0;
01798 if (!keyIsInitialized(key)) return 0;
01799
01800 return keyNameGetNamespace(key->key);
01801 }
01802
01803
01813 int keyIsDir(const Key *key) {
01814 if (!key) return 0;
01815 if (!keyIsInitialized(key)) return 0;
01816
01817 return (S_ISDIR(key->access) || (key->type==KEY_TYPE_DIR));
01818 }
01819
01820
01830 int keyIsLink(const Key *key) {
01831 if (!key) return 0;
01832 if (!keyIsInitialized(key)) return 0;
01833
01834 return (S_ISLNK(key->access) || (key->type==KEY_TYPE_LINK));
01835 }
01836
01837
01847 size_t keyNameGetRootNameSize(const char *keyName) {
01848 char *end;
01849 int length=strlen(keyName);
01850
01851 if (!length) return 0;
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863 end=strchr(keyName,RG_KEY_DELIM);
01864 if (!end)
01865 end = (char *)keyName + length;
01866
01867 return end-keyName;
01868 }
01869
01870
01871
01872
01883 size_t keyGetRootNameSize(const Key *key) {
01884 if (!key) return 0;
01885 if (!keyIsInitialized(key)) return 0;
01886 if (!key->key) return 0;
01887
01888 return keyNameGetRootNameSize(key->key);
01889 }
01890
01891
01892
01893
01894
01906 size_t keyGetFullRootNameSize(const Key *key) {
01907 size_t size=0;
01908
01909 if (keyIsUser(key)) {
01910 if (key->userDomain) size=strblen(key->userDomain);
01911 else size=strblen(getenv("USER"));
01912 }
01913
01914 return size+keyNameGetRootNameSize(key->key);
01915 }
01916
01917
01918
01929 size_t keyNameGetBaseNameSize(const char *keyName) {
01930 char *end;
01931 size_t size,keySize;
01932 unsigned char found=0;
01933
01934 if (!(keySize=strblen(keyName))) return 0;
01935
01936 size=keyNameGetRootNameSize(keyName);
01937 if (!size || size==keySize) return 0;
01938
01939
01940
01941
01942
01943
01944
01945 end=strrchr(keyName,RG_KEY_DELIM);
01946 if (*(end-1)!='\\') return keyName+keySize-(end+1);
01947
01948
01949
01950
01951
01952
01953
01954
01955 while (!found) {
01956 end--;
01957 if (*end=='.') found=1;
01958 }
01959 return keyName+keySize-(end+1);
01960 }
01961
01962
01963
01964
01975 size_t keyGetBaseNameSize(const Key *key) {
01976 if (!key) return 0;
01977 if (!keyIsInitialized(key)) return 0;
01978 if (!key->key) return 0;
01979
01980 return keyNameGetBaseNameSize(key->key);
01981 }
01982
01983
01984
01985
02004 size_t keyGetRootName(const Key *key, char *returned, size_t maxSize) {
02005 size_t size;
02006
02007 if (!key || !keyIsInitialized(key)) {
02008 errno=KDB_RET_UNINITIALIZED;
02009 return -1;
02010 }
02011
02012 if (!key->key) {
02013 errno=KDB_RET_NOKEY;
02014 return -1;
02015 }
02016
02017 if (!(size=keyGetRootNameSize(key))) {
02018 errno=KDB_RET_NOKEY;
02019 return -1;
02020 }
02021
02022 if (maxSize < size) {
02023 errno=KDB_RET_TRUNC;
02024 return -1;
02025 } else strncpy(returned,key->key,size);
02026 return size;
02027 }
02028
02029
02030
02048 size_t keyGetFullRootName(const Key *key, char *returned, size_t maxSize) {
02049 size_t size;
02050 size_t userSize;
02051 char *cursor;
02052
02053 if (!key || !keyIsInitialized(key)) {
02054 errno=KDB_RET_UNINITIALIZED;
02055 return 0;
02056 }
02057
02058 if (!key->key) {
02059 errno=KDB_RET_NOKEY;
02060 return 0;
02061 }
02062
02063 if (!(size=keyGetFullRootNameSize(key))) {
02064 errno=KDB_RET_NOKEY;
02065 return 0;
02066 }
02067
02068 if (maxSize < size) {
02069 errno=KDB_RET_TRUNC;
02070 return 0;
02071 }
02072
02073 userSize = keyGetRootNameSize (key);
02074 strncpy(returned,key->key, userSize);
02075 if (keyIsUser(key)) {
02076 cursor = returned + userSize;
02077 *cursor = ':'; cursor++;
02078 if (key->userDomain)
02079 strncpy (cursor, key->userDomain, size - userSize);
02080 else
02081 strncpy (cursor, getenv("USER"), size - userSize);
02082 }
02083
02084 return size;
02085 }
02086
02087
02088
02102 size_t keyGetBaseName(const Key *key, char *returned, size_t maxSize) {
02103 size_t size;
02104 size_t keySize;
02105
02106 if (!key) {
02107 errno=KDB_RET_NULLKEY;
02108 return 0;
02109 }
02110
02111 if (!keyIsInitialized(key)) {
02112 errno=KDB_RET_UNINITIALIZED;
02113 return 0;
02114 }
02115
02116 if (!(size=keyGetBaseNameSize(key))) {
02117 errno=KDB_RET_NOKEY;
02118 return 0;
02119 }
02120
02121 keySize=strblen(key->key);
02122
02123 if (maxSize < size) {
02124 strncpy(returned,key->key+keySize-size,maxSize);
02125 errno=KDB_RET_TRUNC;
02126 return size;
02127 } else strncpy(returned,key->key+keySize-size,size);
02128
02129 return size;
02130 }
02131
02132
02133
02143 int keySetFlag(Key *key) {
02144 if (!key || !keyIsInitialized(key)) {
02145 errno=KDB_RET_UNINITIALIZED;
02146 return -1;
02147 }
02148
02149 key->flags|=KEY_FLAG_FLAG;
02150
02151 return 0;
02152 }
02153
02154
02155
02165 int keyClearFlag(Key *key) {
02166 if (!key || !keyIsInitialized(key)) {
02167 errno=KDB_RET_UNINITIALIZED;
02168 return -1;
02169 }
02170
02171 key->flags &= ~KEY_FLAG_FLAG;
02172
02173 return 0;
02174 }
02175
02176
02177
02178
02179
02180
02190 int keyGetFlag(const Key *key) {
02191 if (!key || !keyIsInitialized(key)) {
02192 errno=KDB_RET_UNINITIALIZED;
02193 return 0;
02194 }
02195
02196 return (key->flags | KEY_FLAG_FLAG) ? 1:0;
02197 }
02198
02231 int ksInit(KeySet *ks) {
02232 ks->start=ks->end=ks->cursor=0;
02233 ks->size=0;
02234
02235 return 0;
02236 }
02237
02238
02253 int ksClose(KeySet *ks) {
02254 if (ks->size) {
02255 while (ks->size) {
02256 Key *destroyer=ks->start;
02257 ks->start=destroyer->next;
02258 keyClose(destroyer);
02259 free(destroyer);
02260 --ks->size;
02261 }
02262 }
02263 ks->cursor=ks->end=ks->start;
02264 return 0;
02265 }
02266
02267
02268
02269
02270
02275 size_t ksGetSize(KeySet *ks) {
02276 return ks->size;
02277 }
02278
02279
02294 Key *ksNext(KeySet *ks) {
02295 if (ks->cursor) ks->cursor=ks->cursor->next;
02296 else ks->cursor=ks->start;
02297
02298 return ks->cursor;
02299 }
02300
02301
02302
02313 int ksRewind(KeySet *ks) {
02314 ks->cursor=0;
02315 return 0;
02316 }
02317
02318
02319
02328 Key *ksCurrent(const KeySet *ks) {
02329 return ks->cursor;
02330 }
02331
02332
02333
02334
02352 size_t ksInsert(KeySet *ks, Key *toInsert) {
02353 toInsert->next=ks->start;
02354 ks->start=toInsert;
02355 if (!ks->end) ks->end=toInsert;
02356 return ++ks->size;
02357 }
02358
02359
02360
02361
02375 size_t ksInsertKeys(KeySet *ks, KeySet *toInsert) {
02376 if (toInsert->size) {
02377 toInsert->end->next=ks->start;
02378 ks->start=toInsert->start;
02379
02380 ks->size+=toInsert->size;
02381
02382
02383 toInsert->start=toInsert->end=toInsert->cursor=0;
02384 toInsert->size=0;
02385 }
02386 return ks->size;
02387 }
02388
02389
02390
02408 size_t ksAppend(KeySet *ks, Key *toAppend) {
02409 toAppend->next=0;
02410 if (ks->end) ks->end->next=toAppend;
02411 if (!ks->start) ks->start=toAppend;
02412 ks->end=toAppend;
02413 return ++ks->size;
02414 }
02415
02416
02417
02431 size_t ksAppendKeys(KeySet *ks, KeySet *toAppend) {
02432 if (toAppend->size) {
02433 if (ks->end) {
02434 ks->end->next=toAppend->start;
02435 ks->end=toAppend->end;
02436 } else {
02437 ks->end=toAppend->end;
02438 ks->start=toAppend->start;
02439 }
02440
02441 ks->size+=toAppend->size;
02442
02443
02444 toAppend->start=toAppend->end=toAppend->cursor=0;
02445 toAppend->size=0;
02446 }
02447 return ks->size;
02448 }
02449
02450
02451
02452
02453
02454
02455
02483 int ksCompare(KeySet *ks1, KeySet *ks2, KeySet *removed) {
02484 int flagRemoved=1;
02485 Key *ks1Cursor=0;
02486 Key *ks2Cursor=0;
02487
02488 Key *ks1PrevCursor=0;
02489
02490 ks1Cursor=ks1->start;
02491 while (ks1Cursor) {
02492 Key *ks2PrevCursor=0;
02493 flagRemoved=1;
02494
02495 for (ks2Cursor=ks2->start; ks2Cursor; ks2Cursor=ks2Cursor->next) {
02496 u_int32_t flags=keyCompare(ks1Cursor,ks2Cursor);
02497
02498 if (!(flags & (KEY_FLAG_HASKEY | KEY_FLAG_HASDOMAIN))) {
02499
02500 flagRemoved=0;
02501
02502
02503 if (ks2PrevCursor) ks2PrevCursor->next=ks2Cursor->next;
02504 else ks2->start=ks2Cursor->next;
02505 if (ks2->end==ks2Cursor) ks2->end=ks2PrevCursor;
02506 ks2->size--;
02507
02508 if (flags) {
02509
02510
02511
02512 if (ks1PrevCursor) ks1PrevCursor->next=ks2Cursor;
02513 else ks1->start=ks2Cursor;
02514 if (ks1->end==ks1Cursor) ks1->end=ks2Cursor;
02515 ks2Cursor->next=ks1Cursor->next;
02516
02517
02518 keyClose(ks1Cursor); free(ks1Cursor);
02519
02520
02521 ks1Cursor=ks2Cursor;
02522 } else {
02523
02524
02525
02526 keyClose(ks2Cursor);
02527 free(ks2Cursor);
02528 }
02529
02530 break;
02531 }
02532 ks2PrevCursor=ks2Cursor;
02533
02534 }
02535
02536 if (flagRemoved) {
02537
02538
02539
02540
02541 if (ks1PrevCursor) ks1PrevCursor->next=ks1Cursor->next;
02542 else ks1->start=ks1Cursor->next;
02543 if (ks1->end==ks1Cursor) ks1->end=ks1PrevCursor;
02544 ks1->size--;
02545
02546
02547 ksAppend(removed,ks1Cursor);
02548
02549
02550 if (ks1PrevCursor) ks1Cursor=ks1PrevCursor->next;
02551 else ks1Cursor=ks1->start;
02552 } else {
02553 ks1PrevCursor=ks1Cursor;
02554 ks1Cursor=ks1Cursor->next;
02555 }
02556 }
02557
02558
02559 ksAppendKeys(ks1,ks2);
02560
02561 return 0;
02562 }
02563
02564
02565
02566
02581 size_t ksToStream(const KeySet *ks, FILE* stream, unsigned long options) {
02582 size_t written=0;
02583 Key *key=0;
02584
02585 if (options & KDB_O_XMLHEADERS) {
02586 written+=fprintf(stream,"<?xml version=\"1.0\" encoding=\"%s\"?>\n",
02587 nl_langinfo(CODESET));
02588 written+=fprintf(stream,
02589 "<!DOCTYPE keyset PUBLIC \"-//Avi Alkalay//DTD Elektra 0.1.0//EN\" \"http://elektra.sf.net/dtd/elektra.dtd\">\n\n\n");
02590 written+=fprintf(stream,
02591 "<!-- Generated by Elektra API. Total of %d keys. -->\n\n\n\n",ks->size);
02592 }
02593
02594 written+=fprintf(stream,"<keyset>\n\n\n");
02595
02596 for (key=ks->start; key; key=key->next)
02597 written+=keyToStream(key,stream,options);
02598
02599 written+=fprintf(stream,"</keyset>\n");
02600 return written;
02601 }
02602
02603