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
00188 int keyNeedsSync(const Key *key) {
00189 if (!key) return 0;
00190 return (key->flags & KEY_FLAG_NEEDSYNC);
00191 }
00192
00193
00194
00203 u_int8_t keyGetType(const Key *key) {
00204 if (!key || !keyIsInitialized(key)) {
00205 errno=KDB_RET_UNINITIALIZED;
00206 return KEY_TYPE_UNDEFINED;
00207 }
00208
00209 return key->type;
00210 }
00211
00212
00276 u_int8_t keySetType(Key *key,u_int8_t newType) {
00277 mode_t dirSwitch=0111;
00278
00279 if (!key) {
00280 errno=KDB_RET_UNINITIALIZED;
00281 return KEY_TYPE_UNDEFINED;
00282 }
00283 if (!keyIsInitialized(key)) keyInit(key);
00284
00285 switch (newType) {
00286 case KEY_TYPE_DIR:
00287 key->type=KEY_TYPE_DIR;
00288 dirSwitch=umask(0); umask(dirSwitch);
00289 dirSwitch=0111 & ~dirSwitch;
00290 key->access|=dirSwitch | S_IFDIR;
00291 keySetRaw(key,0,0);
00292 break;
00293 default:
00294 key->type=newType;
00295 key->access &= ~(S_IFDIR | dirSwitch);
00296 key->flags |= KEY_FLAG_NEEDSYNC;
00297 }
00298 return key->type;
00299 }
00300
00301
00302
00311 size_t keyGetDataSize(const Key *key) {
00312 if (!key || !keyIsInitialized(key)) {
00313 errno=KDB_RET_UNINITIALIZED;
00314 return -1;
00315 }
00316
00317 return key->dataSize;
00318 }
00319
00320
00321 size_t keyGetRecordSize(const Key *key) {
00322 if (!key || !keyIsInitialized(key)) {
00323 errno=KDB_RET_UNINITIALIZED;
00324 return -1;
00325 }
00326
00327 return key->recordSize;
00328 }
00329
00330
00331
00332
00340 size_t keyGetNameSize(const Key *key) {
00341 if (!key || !keyIsInitialized(key)) {
00342 errno=KDB_RET_UNINITIALIZED;
00343 return 0;
00344 }
00345
00346 if (key->key) return strblen(key->key);
00347 else return 0;
00348 }
00349
00350
00351
00352
00360 size_t keyGetFullNameSize(const Key *key) {
00361 size_t returnedSize;
00362
00363 if (!key || !keyIsInitialized(key)) {
00364 errno=KDB_RET_UNINITIALIZED;
00365 return -1;
00366 }
00367
00368 if (!key->key) return 0;
00369
00370 returnedSize=strblen(key->key);
00371
00372 if (!strncmp("user",key->key,sizeof("user")-1) && key->userDomain)
00373 returnedSize+=strblen(key->userDomain);
00374
00375 return returnedSize;
00376 }
00377
00378
00379
00388 size_t keyGetFullName(const Key *key, char *returnedName, size_t maxSize) {
00389 size_t userSize=sizeof("user")-1;
00390 size_t userDomainSize,length;
00391 char *cursor;
00392
00393 length=keyGetFullNameSize(key);
00394 if (length < 0) return length;
00395 if (length > maxSize) {
00396 errno=KDB_RET_TRUNC;
00397 return -1;
00398 }
00399
00400 cursor=returnedName;
00401 if (!strncmp("user",key->key,userSize)) {
00402 strncpy(cursor,key->key,userSize);
00403 cursor+=userSize;
00404 if (key->userDomain) {
00405 *cursor=':'; ++cursor;
00406 userDomainSize=strblen(key->userDomain)-1;
00407 strcpy(cursor,key->userDomain);
00408 cursor+=userDomainSize;
00409 }
00410 strcpy(cursor,key->key+userSize);
00411 } else strcpy(cursor,key->key);
00412
00413 return length;
00414 }
00415
00416
00417
00418
00427 size_t keyGetName(const Key *key, char *returnedName, size_t maxSize) {
00428 size_t bytes;
00429
00430 if (!key || !keyIsInitialized(key)) {
00431 errno=KDB_RET_UNINITIALIZED;
00432 return 0;
00433 }
00434
00435 if (!key->key) {
00436 errno=KDB_RET_NOKEY;
00437 return 0;
00438 }
00439
00440 bytes=strblen(strncpy(returnedName,key->key,maxSize));
00441 if (maxSize < strblen(key->key)) {
00442 errno=KDB_RET_TRUNC;
00443 return 0;
00444 }
00445 return bytes;
00446 }
00447
00448
00449
00450
00451
00474 size_t keySetName(Key *key, const char *newName) {
00475 size_t length;
00476 size_t rootLength, userLength, systemLength, userDomainLength;
00477 size_t keyNameSize=1;
00478
00479 if (!key) {
00480 errno=KDB_RET_UNINITIALIZED;
00481 return 0;
00482 }
00483 if (!keyIsInitialized(key)) keyInit(key);
00484
00485
00486 if (!newName || !(length=strlen(newName))) {
00487 if (key->key) {
00488 free(key->key);
00489 key->key=0;
00490 }
00491 key->flags &= ~(KEY_FLAG_HASKEY | KEY_FLAG_NEEDSYNC);
00492 return 0;
00493 }
00494
00495
00496 while (newName[length]==RG_KEY_DELIM) {
00497 length--;
00498 }
00499
00500 rootLength=keyNameGetRootNameSize(newName);
00501 if (!rootLength) {
00502 errno=KDB_RET_INVALIDKEY;
00503 return 0;
00504 }
00505 userLength=sizeof("user")-1;
00506 systemLength=sizeof("system")-1;
00507 userDomainLength=rootLength-userLength-1;
00508 if (userDomainLength<0) userDomainLength=0;
00509
00510 if (!strncmp("user",newName,userLength<length?userLength:length)) {
00511
00512 if (length > userLength) {
00513
00514 if (*(newName+userLength)==':') {
00515
00516 if (userDomainLength > 0) {
00517 key->userDomain=realloc(key->userDomain,userDomainLength+1);
00518 strncpy(key->userDomain,newName+userLength+1,userDomainLength);
00519 key->userDomain[userDomainLength]=0;
00520 }
00521 keyNameSize+=length-userDomainLength-1;
00522 } else if (*(newName+userLength)!=RG_KEY_DELIM) {
00523
00524 errno=KDB_RET_INVALIDKEY;
00525 return 0;
00526 } else {
00527
00528 keyNameSize+=length;
00529 }
00530 } else {
00531
00532 keyNameSize+=userLength;
00533 }
00534
00535 key->key=realloc(key->key,keyNameSize);
00536
00537
00538 if (!key->key) return 0;
00539
00540 strcpy(key->key,"user");
00541 strncpy(key->key+userLength,newName+rootLength,length-rootLength);
00542 key->key[keyNameSize-1]=0;
00543
00544 if (!key->userDomain) {
00545 size_t bsize=strblen(getenv("USER"));
00546
00547 if (!bsize) {}
00548 else {
00549 key->userDomain=malloc(bsize);
00550 strncpy(key->userDomain,getenv("USER"),bsize);
00551 }
00552 }
00553
00554 } else if (!strncmp("system",newName,systemLength<length?systemLength:length)) {
00555
00556 if (length > systemLength && *(newName+systemLength)!=RG_KEY_DELIM) {
00557
00558 errno=KDB_RET_INVALIDKEY;
00559 return 0;
00560 }
00561 keyNameSize+=length;
00562 key->key=realloc(key->key,keyNameSize);
00563
00564
00565 if (!key->key) return 0;
00566
00567 strncpy(key->key,newName,length);
00568 key->key[keyNameSize-1]=0;
00569 } else {
00570
00571 errno=KDB_RET_INVALIDKEY;
00572 return 0;
00573 }
00574
00575 key->flags |= KEY_FLAG_HASKEY | KEY_FLAG_NEEDSYNC;
00576
00577 return keyNameSize;
00578 }
00579
00580
00581
00603 size_t keyGetOwner(const Key *key, char *returned, size_t maxSize) {
00604 size_t bytes;
00605
00606 if (!key || !keyIsInitialized(key)) {
00607 errno=KDB_RET_UNINITIALIZED;
00608 return 0;
00609 }
00610
00611 if (!key->userDomain) {
00612 errno=KDB_RET_NODOMAIN;
00613 return 0;
00614 }
00615
00616 if (maxSize < (bytes=strblen(key->userDomain))) {
00617 errno=KDB_RET_TRUNC;
00618 return 0;
00619 } else strcpy(returned,key->userDomain);
00620 return bytes;
00621 }
00622
00623
00636 size_t keySetOwner(Key *key, const char *userDomain) {
00637 size_t size;
00638
00639 if (!key) {
00640 errno=KDB_RET_UNINITIALIZED;
00641 return -1;
00642 }
00643 if (!keyIsInitialized(key)) keyInit(key);
00644
00645 if ((size=strblen(userDomain)) > 0) {
00646 if (key->userDomain) {
00647 key->userDomain=realloc(key->userDomain,size);
00648 } else {
00649 key->userDomain=malloc(size);
00650 }
00651 if (!key->userDomain) return -1;
00652
00653 strcpy(key->userDomain,userDomain);
00654 key->flags |= KEY_FLAG_HASDOMAIN | KEY_FLAG_NEEDSYNC;
00655 return size;
00656 } else if (key->userDomain) {
00657 free(key->userDomain);
00658 key->userDomain=0;
00659 key->flags &= ~(KEY_FLAG_HASDOMAIN | KEY_FLAG_NEEDSYNC);
00660 }
00661 return 0;
00662 }
00663
00664
00665
00666
00678 size_t keyGetComment(const Key *key, char *returnedDesc, size_t maxSize) {
00679 size_t bytes;
00680
00681 if (!key || !keyIsInitialized(key)) {
00682 errno=KDB_RET_UNINITIALIZED;
00683 return 0;
00684 }
00685
00686 if (!key->comment) {
00687 errno=KDB_RET_NODESC;
00688 return 0;
00689 }
00690
00691 bytes=strblen(strncpy(returnedDesc,key->comment,maxSize));
00692 if (maxSize < strblen(key->comment)) {
00693 errno=KDB_RET_TRUNC;
00694 return 0;
00695 }
00696 return bytes;
00697 }
00698
00699
00700
00711 size_t keySetComment(Key *key, const char *newComment) {
00712 size_t size;
00713
00714 if (!key) {
00715 errno=KDB_RET_UNINITIALIZED;
00716 return 0;
00717 }
00718 if (!keyIsInitialized(key)) keyInit(key);
00719
00720 if (newComment && (size=strblen(newComment)) > 0) {
00721 if (key->flags & KEY_FLAG_HASCOMMENT) {
00722 key->comment=realloc(key->comment,size);
00723 } else {
00724 key->comment=malloc(size);
00725 }
00726 if (!key->comment) return 0;
00727
00728 strcpy(key->comment,newComment);
00729 key->flags |= KEY_FLAG_HASCOMMENT | KEY_FLAG_NEEDSYNC;
00730 return key->commentSize=size;
00731 } else if (key->flags & KEY_FLAG_HASCOMMENT) {
00732 free(key->comment);
00733 key->comment=0;
00734 key->flags &= ~(KEY_FLAG_HASCOMMENT | KEY_FLAG_NEEDSYNC);
00735 }
00736 return key->commentSize=0;
00737 }
00738
00739
00740
00751 size_t keyGetCommentSize(const Key *key) {
00752 if (!key || !keyIsInitialized(key)) {
00753 errno=KDB_RET_UNINITIALIZED;
00754 return 0;
00755 }
00756
00757 if (!key->comment) {
00758 errno=KDB_RET_NODESC;
00759 return 0;
00760 }
00761
00762 return strblen(key->comment);
00763 }
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
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
00867 size_t keyGetString(const Key *key, char *returnedString, size_t maxSize) {
00868 if (!key || !keyIsInitialized(key)) {
00869 errno=KDB_RET_UNINITIALIZED;
00870 return 0;
00871 }
00872
00873 if (!key->data) {
00874 *returnedString=0;
00875 errno=KDB_RET_NODATA;
00876 return 0;
00877 }
00878
00879 if (key->dataSize > maxSize) {
00880 errno=KDB_RET_TRUNC;
00881 return 0;
00882 }
00883
00884 if (key->type < KEY_TYPE_STRING) {
00885 errno=KDB_RET_TYPEMISMATCH;
00886 return 0;
00887 }
00888
00889 strcpy(returnedString,key->data);
00890 return key->dataSize;
00891 }
00892
00893
00894
00895
00896
00906 size_t keySetString(Key *key, const char *newString) {
00907 size_t ret=newString?strblen(newString):0;
00908
00909 if (!newString || !ret) ret=keySetRaw(key,0,0);
00910 else keySetRaw(key,newString,ret);
00911
00912 keySetType(key,KEY_TYPE_STRING);
00913
00914 return ret;
00915 }
00916
00917
00918
00919
00929 size_t keyGetBinary(const Key *key, void *returnedBinary, size_t maxSize) {
00930 if (!key || !keyIsInitialized(key))
00931 return errno=KDB_RET_UNINITIALIZED;
00932
00933 if (!key->data) {
00934 errno=KDB_RET_NODATA;
00935 return 0;
00936 }
00937
00938 if (key->dataSize > maxSize) {
00939 errno=KDB_RET_TRUNC;
00940 return 0;
00941 }
00942
00943 memcpy(returnedBinary,key->data,key->dataSize);
00944 return key->dataSize;
00945 }
00946
00947
00948
00949
00966 size_t keySetBinary(Key *key, const void *newBinary, size_t dataSize) {
00967 size_t ret=keySetRaw(key,newBinary,dataSize);
00968
00969 keySetType(key,KEY_TYPE_BINARY);
00970
00971 return ret;
00972 }
00973
00974
00975
00976
00989 size_t keySetRaw(Key *key, const void *newBinary, size_t dataSize) {
00990 if (!key) {
00991 errno=KDB_RET_UNINITIALIZED;
00992 return 0;
00993 }
00994 if (!keyIsInitialized(key)) keyInit(key);
00995
00996 if (!dataSize || !newBinary) {
00997 if (key->data) {
00998 free(key->data);
00999 key->data=0;
01000 }
01001 key->flags &= ~(KEY_FLAG_HASDATA);
01002 key->flags |= KEY_FLAG_NEEDSYNC;
01003 return 0;
01004 }
01005
01006 key->dataSize=dataSize;
01007 if (key->data) key->data=realloc(key->data,key->dataSize);
01008 else key->data=malloc(key->dataSize);
01009
01010 if (!key->data) return 0;
01011
01012 memcpy(key->data,newBinary,key->dataSize);
01013 key->flags |= KEY_FLAG_HASDATA | KEY_FLAG_NEEDSYNC;
01014 return key->dataSize;
01015 }
01016
01017
01018
01019
01020 size_t keyGetLink(const Key *key, char *returnedTarget, size_t maxSize) {
01021 if (!key || !keyIsInitialized(key))
01022 return errno=KDB_RET_UNINITIALIZED;
01023
01024 if (!key->data) {
01025 errno=KDB_RET_NODATA;
01026 return 0;
01027 }
01028
01029 if (key->type != KEY_TYPE_LINK) {
01030 errno=KDB_RET_TYPEMISMATCH;
01031 return 0;
01032 }
01033
01034 if (key->dataSize > maxSize) {
01035 errno=KDB_RET_TRUNC;
01036 return 0;
01037 }
01038
01039 strcpy(returnedTarget,key->data);
01040 return key->dataSize;
01041 }
01042
01043
01044
01045
01046
01047 size_t keySetLink(Key *key, const char *target) {
01048 size_t ret=target?strblen(target):0;
01049
01050 if (!target || !ret) ret=keySetRaw(key,0,0);
01051 else keySetRaw(key,target,ret);
01052
01053 keySetType(key,KEY_TYPE_LINK);
01054
01055 return ret;
01056 }
01057
01058
01059
01074 int keyDup(const Key *source, Key *dest) {
01075
01076
01077 keyClose(dest);
01078
01079
01080 *dest=*source;
01081
01082
01083 dest->key=
01084 dest->comment=
01085 dest->userDomain=
01086 dest->data=0;
01087
01088
01089 keySetName(dest,source->key);
01090 keySetComment(dest,source->comment);
01091 keySetOwner(dest,source->userDomain);
01092 keySetRaw(dest,source->data,source->dataSize);
01093
01094 dest->flags=source->flags;
01095
01096 return 0;
01097 }
01098
01099
01100
01112 uid_t keyGetUID(const Key *key) {
01113 if (!key || !keyIsInitialized(key)) {
01114 errno=KDB_RET_UNINITIALIZED;
01115 return -1;
01116 }
01117
01118
01119
01120 return key->uid;
01121 }
01122
01123
01124
01125
01137 int keySetUID(Key *key, uid_t uid) {
01138 if (!key) return errno=KDB_RET_UNINITIALIZED;
01139 if (!keyIsInitialized(key)) keyInit(key);
01140
01141 key->uid=uid;
01142 key->flags |= KEY_FLAG_HASUID | KEY_FLAG_NEEDSYNC;
01143
01144 return 0;
01145 }
01146
01147
01148
01156 gid_t keyGetGID(const Key *key) {
01157 if (!key || !keyIsInitialized(key)) {
01158 errno=KDB_RET_UNINITIALIZED;
01159 return -1;
01160 }
01161
01162
01163
01164 return key->gid;
01165 }
01166
01167
01168
01176 int keySetGID(Key *key, gid_t gid) {
01177 if (!key) return errno=KDB_RET_UNINITIALIZED;
01178 if (!keyIsInitialized(key)) keyInit(key);
01179
01180 key->gid=gid;
01181 key->flags |= KEY_FLAG_HASGID | KEY_FLAG_NEEDSYNC;
01182
01183 return 0;
01184 }
01185
01186
01187
01191 mode_t keyGetAccess(const Key *key) {
01192 if (!key || !keyIsInitialized(key)) {
01193 errno=KDB_RET_UNINITIALIZED;
01194 return -1;
01195 }
01196
01197
01198
01199 return key->access;
01200 }
01201
01202
01203
01204
01208 int keySetAccess(Key *key, mode_t mode) {
01209 if (!key) return errno=KDB_RET_UNINITIALIZED;
01210 if (!keyIsInitialized(key)) keyInit(key);
01211
01212 key->access=mode;
01213 key->flags |= KEY_FLAG_HASPRM | KEY_FLAG_NEEDSYNC;
01214
01215 return 0;
01216 }
01217
01218
01219
01220
01221
01225 time_t keyGetMTime(const Key *key) {
01226 if (!key || !keyIsInitialized(key)) {
01227 errno=KDB_RET_UNINITIALIZED;
01228 return -1;
01229 }
01230
01231
01232 return key->mtime;
01233 }
01234
01235
01236
01240 time_t keyGetATime(const Key *key) {
01241 if (!key || !keyIsInitialized(key)) {
01242 errno=KDB_RET_UNINITIALIZED;
01243 return -1;
01244 }
01245
01246
01247 return key->atime;
01248 }
01249
01250
01254 time_t keyGetCTime(const Key *key) {
01255 if (!key || !keyIsInitialized(key)) {
01256 errno=KDB_RET_UNINITIALIZED;
01257 return -1;
01258 }
01259
01260
01261 return key->ctime;
01262 }
01263
01264
01265
01270 size_t keyGetParentSize(const Key *key) {
01271 char *parentNameEnd;
01272
01273 if (!key || !keyIsInitialized(key)) {
01274 errno=KDB_RET_UNINITIALIZED;
01275 return 0;
01276 }
01277
01278 if (!key->key) {
01279 errno=KDB_RET_NOKEY;
01280 return 0;
01281 }
01282
01283
01284
01285
01286
01287
01288
01289 parentNameEnd=rindex(key->key,RG_KEY_DELIM);
01290
01291 if (!parentNameEnd || parentNameEnd==key->key) {
01292
01293 return 0;
01294 }
01295
01296
01297 if ((parentNameEnd-key->key) == (strlen(key->key)-1)) {
01298 parentNameEnd--;
01299 while (*parentNameEnd!=RG_KEY_DELIM) parentNameEnd--;
01300 }
01301
01302 return parentNameEnd - key->key;
01303 }
01304
01305
01306
01314 size_t keyGetParent(const Key *key, char *returnedParent, size_t maxSize) {
01315 size_t parentSize;
01316
01317 parentSize=keyGetParentSize(key);
01318
01319 if (parentSize > maxSize) {
01320 errno=KDB_RET_TRUNC;
01321 return 0;
01322 } else strncpy(returnedParent,key->key,parentSize);
01323
01324 return parentSize;
01325 }
01326
01327
01328
01339 u_int32_t keyCompare(const Key *key1, const Key *key2) {
01340 u_int32_t ret=0;
01341
01342
01343
01344 if (key1->uid != key2->uid) ret|=KEY_FLAG_HASUID;
01345 if (key1->gid != key2->gid) ret|=KEY_FLAG_HASGID;
01346 if (key1->type != key2->type) ret|=KEY_FLAG_HASTYPE;
01347 if ((key1->access & (S_IRWXU|S_IRWXG|S_IRWXO)) !=
01348 (key2->access & (S_IRWXU|S_IRWXG|S_IRWXO))) ret|=KEY_FLAG_HASPRM;
01349
01350
01351
01352 if (key1->key && key2->key) {
01353 if (strcmp(key1->key,key2->key)) ret|=KEY_FLAG_HASKEY;
01354 } else {
01355 if (key1->key) ret|=KEY_FLAG_HASKEY;
01356 else if (key2->key) ret|=KEY_FLAG_HASKEY;
01357 }
01358
01359 if (key1->comment && key2->comment) {
01360 if (strcmp(key1->comment,key2->comment)) ret|=KEY_FLAG_HASCOMMENT;
01361 } else {
01362 if (key1->comment) ret|=KEY_FLAG_HASCOMMENT;
01363 else if (key2->comment) ret|=KEY_FLAG_HASCOMMENT;
01364 }
01365
01366 if (key1->userDomain && key2->userDomain) {
01367 if (strcmp(key1->userDomain,key2->userDomain)) ret|=KEY_FLAG_HASDOMAIN;
01368 } else {
01369 if (key1->userDomain) ret|=KEY_FLAG_HASDOMAIN;
01370 else if (key2->comment) ret|=KEY_FLAG_HASDOMAIN;
01371 }
01372
01373
01374
01375 if (memcmp(key1->data,key2->data,
01376 (key1->dataSize<=key2->dataSize?key1->dataSize:key2->dataSize)))
01377 ret|=KEY_FLAG_HASDATA;
01378
01379 return ret;
01380 }
01381
01382
01383
01384
01385
01386
01412 size_t keyToStream(const Key *key, FILE* stream, unsigned long options) {
01413 size_t written=0;
01414 char buffer[800];
01415 struct passwd *pwd=0;
01416 struct group *grp=0;
01417
01418
01419 if (!key || !keyIsInitialized(key) || !key->key) {
01420 errno=KDB_RET_UNINITIALIZED;
01421 return 0;
01422 }
01423
01424 keyGetFullName(key,buffer,sizeof(buffer));
01425
01426 if (!(options & KDB_O_NUMBERS)) {
01427 pwd=getpwuid(keyGetUID(key));
01428 grp=getgrgid(keyGetGID(key));
01429 }
01430
01431
01432 written+=fprintf(stream,"<key name=\"%s\"", buffer);
01433
01434 if (options & KDB_O_CONDENSED) written+=fprintf(stream," ");
01435 else written+=fprintf(stream,"\n ");
01436
01437
01438
01439
01440
01441 if (options & KDB_O_NUMBERS) {
01442 written+=fprintf(stream,"type=\"%d\"", keyGetType(key));
01443 } else {
01444 u_int8_t type=keyGetType(key);
01445 buffer[0]=0;
01446
01447 switch (type) {
01448 case KEY_TYPE_STRING:
01449 strcpy(buffer,"string");
01450 break;
01451 case KEY_TYPE_BINARY:
01452 strcpy(buffer,"binary");
01453 break;
01454 case KEY_TYPE_LINK:
01455 strcpy(buffer,"link");
01456 break;
01457 case KEY_TYPE_DIR:
01458 strcpy(buffer,"directory");
01459 break;
01460 }
01461 if (buffer[0]) written+=fprintf(stream,"type=\"%s\"", buffer);
01462 else written+=fprintf(stream,"type=\"%d\"", type);
01463 }
01464
01465
01466
01467
01468 if (pwd) written+=fprintf(stream," uid=\"%s\"",pwd->pw_name);
01469 else written+=fprintf(stream, " uid=\"%d\"",keyGetUID(key));
01470
01471 if (grp) written+=fprintf(stream," gid=\"%s\"",grp->gr_name);
01472 else written+=fprintf(stream, " gid=\"%d\"",keyGetGID(key));
01473
01474 written+=fprintf(stream," mode=\"0%o\">",
01475 keyGetAccess(key) & (S_IRWXU|S_IRWXG|S_IRWXO));
01476
01477
01478
01479 if (!(options & KDB_O_CONDENSED) && (key->data || key->comment))
01480 written+=fprintf(stream,"\n\n ");
01481
01482 if (key->data)
01483 written+=
01484 fprintf(stream,"<value><![CDATA[%s]]></value>",(char *)key->data);
01485
01486
01487
01488 if (!(options & KDB_O_CONDENSED)) {
01489 written+=fprintf(stream,"\n");
01490 if (key->comment) written+=fprintf(stream," ");
01491 }
01492
01493 if (key->comment) {
01494 written+=fprintf(stream,"<comment><![CDATA[%s]]></comment>", key->comment);
01495 if (!(options & KDB_O_CONDENSED))
01496 written+=fprintf(stream,"\n");
01497 }
01498
01499 written+=fprintf(stream,"</key>");
01500
01501 if (!(options & KDB_O_CONDENSED))
01502 written+=fprintf(stream,"\n\n\n\n\n\n");
01503
01504 return written;
01505 }
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
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
01665 int keyNameIsSystem(const char *keyName) {
01666 if (!keyName) return 0;
01667 if (!strlen(keyName)) return 0;
01668
01669 if (!strncmp("system",keyName,sizeof("system")-1)) return 1;
01670 return 0;
01671 }
01672
01673
01684 int keyNameIsUser(const char *keyName) {
01685 if (!keyName) return 0;
01686 if (!strlen(keyName)) return 0;
01687
01688 if (!strncmp("user",keyName,sizeof("user")-1)) return 1;
01689 return 0;
01690 }
01691
01692
01693
01703 int keyIsSystem(const Key *key) {
01704 if (!key) return 0;
01705 if (!keyIsInitialized(key)) return 0;
01706
01707 return keyNameIsSystem(key->key);
01708 }
01709
01710
01711
01721 int keyIsUser(const Key *key) {
01722 if (!key) return 0;
01723 if (!keyIsInitialized(key)) return 0;
01724
01725 return keyNameIsUser(key->key);
01726 }
01727
01728
01729
01730
01743 int keyNameGetNamespace(const char *keyName) {
01744 if (keyNameIsSystem(keyName)) return KEY_NS_SYSTEM;
01745 if (keyNameIsUser(keyName)) return KEY_NS_USER;
01746 return 0;
01747 }
01748
01749
01750
01763 int keyGetNamespace(const Key *key) {
01764 if (!key) return 0;
01765 if (!keyIsInitialized(key)) return 0;
01766
01767 return keyNameGetNamespace(key->key);
01768 }
01769
01770
01780 int keyIsDir(const Key *key) {
01781 if (!key) return 0;
01782 if (!keyIsInitialized(key)) return 0;
01783
01784 return (S_ISDIR(key->access) || (key->type==KEY_TYPE_DIR));
01785 }
01786
01787
01797 int keyIsLink(const Key *key) {
01798 if (!key) return 0;
01799 if (!keyIsInitialized(key)) return 0;
01800
01801 return (S_ISLNK(key->access) || (key->type==KEY_TYPE_LINK));
01802 }
01803
01804
01814 size_t keyNameGetRootNameSize(const char *keyName) {
01815 char *end;
01816 int length=strlen(keyName);
01817
01818 if (!length) return 0;
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830 end=strchr(keyName,RG_KEY_DELIM);
01831 if (!end)
01832 end = (char *)keyName + length;
01833
01834 return end-keyName;
01835 }
01836
01837
01838
01839
01850 size_t keyGetRootNameSize(const Key *key) {
01851 if (!key) return 0;
01852 if (!keyIsInitialized(key)) return 0;
01853 if (!key->key) return 0;
01854
01855 return keyNameGetRootNameSize(key->key);
01856 }
01857
01858
01859
01860
01861
01873 size_t keyGetFullRootNameSize(const Key *key) {
01874 size_t size=0;
01875
01876 if (keyIsUser(key)) {
01877 if (key->userDomain) size=strblen(key->userDomain);
01878 else size=strblen(getenv("USER"));
01879 }
01880
01881 return size+keyNameGetRootNameSize(key->key);
01882 }
01883
01884
01885
01896 size_t keyNameGetBaseNameSize(const char *keyName) {
01897 char *end;
01898 size_t size,keySize;
01899 unsigned char found=0;
01900
01901 if (!(keySize=strblen(keyName))) return 0;
01902
01903 size=keyNameGetRootNameSize(keyName);
01904 if (!size || size==keySize) return 0;
01905
01906
01907
01908
01909
01910
01911
01912 end=strrchr(keyName,RG_KEY_DELIM);
01913 if (*(end-1)!='\\') return keyName+keySize-(end+1);
01914
01915
01916
01917
01918
01919
01920
01921
01922 while (!found) {
01923 end--;
01924 if (*end=='.') found=1;
01925 }
01926 return keyName+keySize-(end+1);
01927 }
01928
01929
01930
01931
01942 size_t keyGetBaseNameSize(const Key *key) {
01943 if (!key) return 0;
01944 if (!keyIsInitialized(key)) return 0;
01945 if (!key->key) return 0;
01946
01947 return keyNameGetBaseNameSize(key->key);
01948 }
01949
01950
01951
01952
01971 size_t keyGetRootName(const Key *key, char *returned, size_t maxSize) {
01972 size_t size;
01973
01974 if (!key || !keyIsInitialized(key)) {
01975 errno=KDB_RET_UNINITIALIZED;
01976 return -1;
01977 }
01978
01979 if (!key->key) {
01980 errno=KDB_RET_NOKEY;
01981 return -1;
01982 }
01983
01984 if (!(size=keyGetRootNameSize(key))) {
01985 errno=KDB_RET_NOKEY;
01986 return -1;
01987 }
01988
01989 if (maxSize < size) {
01990 errno=KDB_RET_TRUNC;
01991 return -1;
01992 } else strncpy(returned,key->key,size);
01993 return size;
01994 }
01995
01996
01997
02015 size_t keyGetFullRootName(const Key *key, char *returned, size_t maxSize) {
02016 size_t size;
02017
02018 if (!key || !keyIsInitialized(key)) {
02019 errno=KDB_RET_UNINITIALIZED;
02020 return 0;
02021 }
02022
02023 if (!key->key) {
02024 errno=KDB_RET_NOKEY;
02025 return 0;
02026 }
02027
02028 if (!(size=keyGetFullRootNameSize(key))) {
02029 errno=KDB_RET_NOKEY;
02030 return 0;
02031 }
02032
02033 if (maxSize < size) {
02034 errno=KDB_RET_TRUNC;
02035 return 0;
02036 } else strncpy(returned,key->key,size);
02037 return size;
02038 }
02039
02040
02041
02055 size_t keyGetBaseName(const Key *key, char *returned, size_t maxSize) {
02056 size_t size;
02057 size_t keySize;
02058
02059 if (!key) {
02060 errno=KDB_RET_NULLKEY;
02061 return 0;
02062 }
02063
02064 if (!keyIsInitialized(key)) {
02065 errno=KDB_RET_UNINITIALIZED;
02066 return 0;
02067 }
02068
02069 if (!(size=keyGetBaseNameSize(key))) {
02070 errno=KDB_RET_NOKEY;
02071 return 0;
02072 }
02073
02074 keySize=strblen(key->key);
02075
02076 if (maxSize < size) {
02077 strncpy(returned,key->key+keySize-size,maxSize);
02078 errno=KDB_RET_TRUNC;
02079 return size;
02080 } else strncpy(returned,key->key+keySize-size,size);
02081
02082 return size;
02083 }
02084
02085
02086
02096 int keySetFlag(Key *key) {
02097 if (!key || !keyIsInitialized(key)) {
02098 errno=KDB_RET_UNINITIALIZED;
02099 return -1;
02100 }
02101
02102 key->flags|=KEY_FLAG_FLAG;
02103
02104 return 0;
02105 }
02106
02107
02108
02118 int keyClearFlag(Key *key) {
02119 if (!key || !keyIsInitialized(key)) {
02120 errno=KDB_RET_UNINITIALIZED;
02121 return -1;
02122 }
02123
02124 key->flags &= ~KEY_FLAG_FLAG;
02125
02126 return 0;
02127 }
02128
02129
02130
02131
02132
02133
02143 int keyGetFlag(const Key *key) {
02144 if (!key || !keyIsInitialized(key)) {
02145 errno=KDB_RET_UNINITIALIZED;
02146 return 0;
02147 }
02148
02149 return (key->flags | KEY_FLAG_FLAG) ? 1:0;
02150 }
02151
02184 int ksInit(KeySet *ks) {
02185 ks->start=ks->end=ks->cursor=0;
02186 ks->size=0;
02187
02188 return 0;
02189 }
02190
02191
02202 int ksClose(KeySet *ks) {
02203 if (ks->size) {
02204 Key *cursor=ks->start;
02205 while (ks->size) {
02206 Key *destroyer=cursor;
02207 cursor=cursor->next;
02208 keyClose(destroyer);
02209 free(destroyer);
02210 --ks->size;
02211 }
02212 }
02213 ks->start=ks->end=ks->cursor;
02214 return 0;
02215 }
02216
02217
02232 Key *ksNext(KeySet *ks) {
02233 if (!ks->cursor) ks->cursor=ks->start;
02234 else ks->cursor=ks->cursor->next;
02235
02236 return ks->cursor;
02237 }
02238
02239
02240
02251 int ksRewind(KeySet *ks) {
02252 ks->cursor=0;
02253 return 0;
02254 }
02255
02256
02257
02266 Key *ksCurrent(const KeySet *ks) {
02267 return ks->cursor;
02268 }
02269
02270
02271
02272
02285 size_t ksInsert(KeySet *ks, Key *toInsert) {
02286 toInsert->next=ks->start;
02287 ks->start=toInsert;
02288 if (!ks->end) ks->end=toInsert;
02289 return ++ks->size;
02290 }
02291
02292
02293
02294
02308 size_t ksInsertKeys(KeySet *ks, KeySet *toInsert) {
02309 if (toInsert->size) {
02310 toInsert->end->next=ks->start;
02311 ks->start=toInsert->start;
02312
02313 ks->size+=toInsert->size;
02314
02315
02316 toInsert->start=toInsert->end=0;
02317 toInsert->size=0;
02318 }
02319 return ks->size;
02320 }
02321
02322
02323
02336 size_t ksAppend(KeySet *ks, Key *toAppend) {
02337 toAppend->next=0;
02338 if (ks->end) ks->end->next=toAppend;
02339 if (!ks->start) ks->start=toAppend;
02340 ks->end=toAppend;
02341 return ++ks->size;
02342 }
02343
02344
02345
02359 size_t ksAppendKeys(KeySet *ks, KeySet *toAppend) {
02360 if (toAppend->size) {
02361 if (ks->end) {
02362 ks->end->next=toAppend->start;
02363 ks->end=toAppend->end;
02364 } else {
02365 ks->end=toAppend->end;
02366 ks->start=toAppend->start;
02367 }
02368
02369 ks->size+=toAppend->size;
02370
02371
02372 toAppend->start=toAppend->end=0;
02373 toAppend->size=0;
02374 }
02375 return ks->size;
02376 }
02377
02378
02379
02380
02381
02382
02383
02411 int ksCompare(KeySet *ks1, KeySet *ks2, KeySet *removed) {
02412 int flagRemoved=1;
02413 Key *ks1Cursor=0;
02414 Key *ks2Cursor=0;
02415
02416 Key *ks1PrevCursor=0;
02417
02418 ks1Cursor=ks1->start;
02419 while (ks1Cursor) {
02420 Key *ks2PrevCursor=0;
02421 flagRemoved=1;
02422
02423 for (ks2Cursor=ks2->start; ks2Cursor; ks2Cursor=ks2Cursor->next) {
02424 u_int32_t flags=keyCompare(ks1Cursor,ks2Cursor);
02425
02426 if (!(flags & (KEY_FLAG_HASKEY | KEY_FLAG_HASDOMAIN))) {
02427
02428 flagRemoved=0;
02429
02430
02431 if (ks2PrevCursor) ks2PrevCursor->next=ks2Cursor->next;
02432 else ks2->start=ks2Cursor->next;
02433 if (ks2->end==ks2Cursor) ks2->end=ks2PrevCursor;
02434 ks2->size--;
02435
02436 if (flags) {
02437
02438
02439
02440 if (ks1PrevCursor) ks1PrevCursor->next=ks2Cursor;
02441 else ks1->start=ks2Cursor;
02442 if (ks1->end==ks1Cursor) ks1->end=ks2Cursor;
02443 ks2Cursor->next=ks1Cursor->next;
02444
02445
02446 keyClose(ks1Cursor); free(ks1Cursor);
02447
02448
02449 ks1Cursor=ks2Cursor;
02450 } else {
02451
02452
02453
02454 keyClose(ks2Cursor);
02455 free(ks2Cursor);
02456 }
02457
02458 break;
02459 }
02460 ks2PrevCursor=ks2Cursor;
02461
02462 }
02463
02464 if (flagRemoved) {
02465
02466
02467
02468
02469 if (ks1PrevCursor) ks1PrevCursor->next=ks1Cursor->next;
02470 else ks1->start=ks1Cursor->next;
02471 if (ks1->end==ks1Cursor) ks1->end=ks1PrevCursor;
02472 ks1->size--;
02473
02474
02475 ksAppend(removed,ks1Cursor);
02476
02477
02478 if (ks1PrevCursor) ks1Cursor=ks1PrevCursor->next;
02479 else ks1Cursor=ks1->start;
02480 } else {
02481 ks1PrevCursor=ks1Cursor;
02482 ks1Cursor=ks1Cursor->next;
02483 }
02484 }
02485
02486
02487 ksAppendKeys(ks1,ks2);
02488
02489 return 0;
02490 }
02491
02492
02493
02494
02509 size_t ksToStream(const KeySet *ks, FILE* stream, unsigned long options) {
02510 size_t written=0;
02511 Key *key=0;
02512
02513 if (options & KDB_O_XMLHEADERS) {
02514 written+=fprintf(stream,"<?xml version=\"1.0\" encoding=\"%s\"?>\n",
02515 nl_langinfo(CODESET));
02516 written+=fprintf(stream,
02517 "<!DOCTYPE keyset PUBLIC \"-//Avi Alkalay//DTD Elektra 0.1.0//EN\" \"http://registry.sf.net/dtd/registry.dtd\">\n\n\n");
02518 written+=fprintf(stream,
02519 "<!-- Generated by Elektra API. Total of %d keys. -->\n\n\n\n",ks->size);
02520 }
02521
02522 written+=fprintf(stream,"<keyset>\n\n\n");
02523
02524 for (key=ks->start; key; key=key->next)
02525 written+=keyToStream(key,stream,options);
02526
02527 written+=fprintf(stream,"</keyset>\n");
02528 return written;
02529 }
02530
02531