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 <stdarg.h>
00028 #ifdef HAVE_STRINGS_H
00029 #include <strings.h>
00030 #endif
00031 #include <string.h>
00032 #include <stdlib.h>
00033 #include <sys/stat.h>
00034 #include <errno.h>
00035 #ifdef HAVE_UNISTD_H
00036 #include <unistd.h>
00037 #endif
00038 #ifdef WIN32
00039 #include <io.h>
00040 #endif
00041 #include <sys/types.h>
00042 #ifdef HAVE_PWD_H
00043 #include <pwd.h>
00044 #endif
00045 #ifdef HAVE_GRP_H
00046 #include <grp.h>
00047 #endif
00048
00049 #ifdef HAVE_LANGINFO_H
00050 #include <langinfo.h>
00051 #endif
00052
00053 #include "kdb.h"
00054 #include "kdbprivate.h"
00055
00065 size_t strblen(const char *s) {
00066 char *found=strchr(s,0);
00067 if (found) return found-s+1;
00068 return 0;
00069 }
00070
00071
00072
00340 Key *keyNew(const char *keyName, ...) {
00341 va_list va;
00342 Key *key;
00343 uint32_t action=0;
00344 uint8_t keyType=KEY_TYPE_UNDEFINED;
00345 uint8_t keyTypeBinary=0;
00346 size_t valueSize=0;
00347
00348 key=(Key *)malloc(sizeof(Key));
00349 if (!key) return 0;
00350 keyInit(key);
00351
00352 if (keyName) {
00353 size_t nameSize;
00354
00355 nameSize=keySetName(key,keyName);
00356 if (! nameSize) {
00357 free(key);
00358 return 0;
00359 }
00360
00361 va_start(va,keyName);
00362
00363 action=va_arg(va,uint32_t);
00364 while (action) {
00365 switch (action) {
00366 case KEY_SWITCH_TYPE:
00367
00368
00369
00370
00371 keyType=(uint8_t)va_arg(va,unsigned int);
00372
00373 keyTypeBinary=(KEY_TYPE_BINARY <= keyType &&
00374 keyType < KEY_TYPE_STRING);
00375
00376 keySetType(key,keyType);
00377
00378 break;
00379 case KEY_SWITCH_VALUE:
00380 if (keyType == KEY_TYPE_UNDEFINED)
00381 keyType=KEY_TYPE_STRING;
00382
00383 if (!keyTypeBinary) {
00384
00385 keySetString(key,va_arg(va,char *));
00386
00387
00388 keySetType(key,keyType);
00389 } else {
00390
00391 valueSize=va_arg(va,size_t);
00392 keySetRaw(key,va_arg(va,void *),valueSize);
00393 }
00394
00395 break;
00396 case KEY_SWITCH_UID:
00397 keySetUID(key,va_arg(va,uid_t));
00398 break;
00399 case KEY_SWITCH_GID:
00400 keySetGID(key,va_arg(va,gid_t));
00401 break;
00402 case KEY_SWITCH_MODE:
00403 keySetAccess(key,va_arg(va,mode_t));
00404 break;
00405 case KEY_SWITCH_DOMAIN:
00406 keySetOwner(key,va_arg(va,char *));
00407 break;
00408 case KEY_SWITCH_COMMENT:
00409 keySetComment(key,va_arg(va,char *));
00410 break;
00411 case KEY_SWITCH_NEEDSYNC: {
00412 int rc=0;
00413 rc=kdbGetKey(key);
00414 if (rc)
00415
00416
00417
00418 key->flags|=KEY_SWITCH_FLAG;
00419 } break;
00420 }
00421 action=va_arg(va,uint32_t);
00422 }
00423 va_end(va);
00424 }
00425 return key;
00426 }
00427
00428
00429
00430
00443 int keyDel(Key *key) {
00444 int rc;
00445
00446 rc=keyClose(key);
00447 free(key);
00448
00449 return rc;
00450 }
00451
00452
00453
00454
00455
00466 int keyIsInitialized(const Key *key) {
00467
00468 return ((key->flags & KEY_SWITCH_INITMASK)==KEY_SWITCH_INITIALIZED);
00469 }
00470
00471
00472
00473
00474
00475
00476
00505 ssize_t keySetName(Key *key, const char *newName) {
00506 size_t length;
00507 size_t rootLength, userLength, systemLength, userDomainLength;
00508 size_t keyNameSize=1;
00509 char *p;
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 if (!newName || !(length=strblen(newName)-1)) {
00520 if (key->key) {
00521 free(key->key);
00522 key->key=0;
00523 }
00524 key->flags &= ~(KEY_SWITCH_NAME | KEY_SWITCH_NEEDSYNC |
00525 KEY_SWITCH_ISSYSTEM | KEY_SWITCH_ISUSER);
00526 return 0;
00527 }
00528
00529
00530 while (length && newName[length]==RG_KEY_DELIM) {
00531 length--;
00532 }
00533
00534 rootLength=keyNameGetRootNameSize(newName);
00535 if (!rootLength) {
00536 errno=KDB_RET_INVALIDKEY;
00537 return -1;
00538 }
00539 userLength=sizeof("user")-1;
00540 systemLength=sizeof("system")-1;
00541 userDomainLength=rootLength-userLength-1;
00542 if (userDomainLength<0) userDomainLength=0;
00543
00544 if (!strncmp("user",newName,userLength<length?userLength:length)) {
00545
00546 if (length > userLength) {
00547
00548 if (*(newName+userLength)==':') {
00549
00550 if (userDomainLength > 0) {
00551 p=realloc(key->userDomain,userDomainLength+1);
00552 if (NULL==p) goto error_mem;
00553 key->userDomain=p;
00554 strncpy(key->userDomain,newName+userLength+1,userDomainLength);
00555 key->userDomain[userDomainLength]=0;
00556 }
00557 keyNameSize+=length-userDomainLength-1;
00558 } else if (*(newName+userLength)!=RG_KEY_DELIM) {
00559
00560 errno=KDB_RET_INVALIDKEY;
00561 return -1;
00562 } else {
00563
00564 keyNameSize+=length;
00565 }
00566 } else {
00567
00568 keyNameSize+=userLength;
00569 }
00570
00571 p=realloc(key->key,keyNameSize);
00572 if (NULL==p) goto error_mem;
00573 key->key=p;
00574
00575
00576 if (!key->key) return -1;
00577
00578 strcpy(key->key,"user");
00579 strncpy(key->key+userLength,newName+rootLength,length-rootLength);
00580 key->key[keyNameSize-1]=0;
00581
00582 if (!key->userDomain) {
00583 size_t bsize=strblen(getenv("USER"));
00584
00585 if (!bsize) {}
00586 else {
00587 key->userDomain=malloc(bsize);
00588 strncpy(key->userDomain,getenv("USER"),bsize);
00589 }
00590 }
00591 key->flags |= KEY_SWITCH_ISUSER;
00592 key->flags &= ~KEY_SWITCH_ISSYSTEM;
00593 } else if (!strncmp("system",newName,systemLength<length?systemLength:length)) {
00594
00595 if (length > systemLength && *(newName+systemLength)!=RG_KEY_DELIM) {
00596
00597 errno=KDB_RET_INVALIDKEY;
00598 return -1;
00599 }
00600 keyNameSize+=length;
00601 p=realloc(key->key,keyNameSize);
00602 if (NULL==p) goto error_mem;
00603 key->key=p;
00604
00605
00606
00607 if (!key->key) return -1;
00608
00609 strncpy(key->key,newName,length);
00610 key->key[keyNameSize-1]=0;
00611
00612 key->flags |= KEY_SWITCH_ISSYSTEM;
00613 key->flags &= ~KEY_SWITCH_ISUSER;
00614 } else {
00615
00616 errno=KDB_RET_INVALIDKEY;
00617 return -1;
00618 }
00619
00620 key->flags |= KEY_SWITCH_NAME | KEY_SWITCH_NEEDSYNC;
00621
00622 return keyNameSize;
00623
00624 error_mem:
00625 errno=KDB_RET_NOMEM;
00626 return -1;
00627 }
00628
00629
00630
00646 ssize_t keyAddBaseName(Key *key,const char *baseName) {
00647 size_t nameSize=0;
00648 size_t newSize=0;
00649 int ndelim=0;
00650 char *p;
00651
00652 if (key->key) nameSize=strblen(key->key)-1;
00653 if (baseName) newSize=strblen(baseName);
00654 else return nameSize;
00655
00656 if (newSize==0) return nameSize;
00657
00658 if (key->key) {
00659
00660 while (nameSize-2 && key->key[nameSize-1]==RG_KEY_DELIM &&
00661 key->key[nameSize-2]!=RG_KEY_DELIM) {
00662 key->key[--nameSize]=0;
00663 }
00664
00665 if (key->key[nameSize-1] != RG_KEY_DELIM) nameSize++;
00666
00667
00668 while (baseName[ndelim] && baseName[ndelim] == RG_KEY_DELIM) {
00669 newSize--;
00670 ndelim++;
00671 }
00672
00673
00674 newSize+=nameSize;
00675 p=realloc(key->key,newSize);
00676 if (NULL == p) {
00677 errno=KDB_RET_NOMEM;
00678 return -1;
00679 }
00680 key->key=p;
00681
00682 if (key->key[nameSize-1] != RG_KEY_DELIM && baseName[ndelim])
00683 strcat(key->key,"/");
00684
00685 strcat(key->key,baseName+ndelim);
00686
00687 } else return keySetName(key,baseName);
00688
00689 return newSize;
00690 }
00691
00692
00693
00694
00710 ssize_t keySetBaseName(Key *key, const char *baseName) {
00711 size_t newSize=strblen(baseName);
00712 char *end;
00713 char *p;
00714
00715 end=strrchr(key->key,'/');
00716
00717 if (end) {
00718 newSize+=end-key->key;
00719 end[1]=0;
00720 p=realloc(key->key,newSize);
00721 if (NULL == p) {
00722 errno=KDB_RET_NOMEM;
00723 return -1;
00724 }
00725 key->key=p;
00726 strcat(key->key,baseName);
00727 return newSize;
00728 } else return keySetName(key,baseName);
00729 }
00730
00731
00732
00733
00741 ssize_t keyGetNameSize(const Key *key) {
00742
00743
00744
00745
00746
00747 if (key->key) return strblen(key->key);
00748 else return 0;
00749 }
00750
00751
00752
00753
00764 ssize_t keyGetName(const Key *key, char *returnedName, size_t maxSize) {
00765 size_t bytes;
00766
00767
00768
00769
00770
00771
00772 if (!key->key) {
00773 errno=KDB_RET_NOKEY;
00774 returnedName[0]=0;
00775 return 0;
00776 }
00777
00778 bytes=strblen(strncpy(returnedName,key->key,maxSize));
00779 if (maxSize < strblen(key->key)) {
00780 errno=KDB_RET_TRUNC;
00781 return -1;
00782 }
00783 return bytes;
00784 }
00785
00786
00787
00799 char *keyStealName(const Key *key) {
00800 return key->key;
00801 }
00802
00803
00804
00805
00806
00807
00815 ssize_t keyGetFullNameSize(const Key *key) {
00816 size_t returnedSize;
00817
00818
00819
00820
00821
00822
00823 if (!key->key) return 0;
00824
00825 returnedSize=strblen(key->key);
00826
00827 if (!strncmp("user",key->key,sizeof("user")-1) && key->userDomain)
00828 returnedSize+=strblen(key->userDomain);
00829
00830 return returnedSize;
00831 }
00832
00833
00834
00835
00845 ssize_t keyGetFullName(const Key *key, char *returnedName, size_t maxSize) {
00846 size_t userSize=sizeof("user")-1;
00847 size_t userDomainSize;
00848 ssize_t length;
00849 char *cursor;
00850
00851 length=keyGetFullNameSize(key);
00852 if (length == 0) {
00853 errno=KDB_RET_NOKEY;
00854 returnedName[0]=0;
00855 return length;
00856 }
00857 if (length < 0) return length;
00858 if (length > maxSize) {
00859 errno=KDB_RET_TRUNC;
00860 return -1;
00861 }
00862
00863 cursor=returnedName;
00864 if (!strncmp("user",key->key,userSize)) {
00865 strncpy(cursor,key->key,userSize);
00866 cursor+=userSize;
00867 if (key->userDomain) {
00868 *cursor=':'; ++cursor;
00869 userDomainSize=strblen(key->userDomain)-1;
00870 strcpy(cursor,key->userDomain);
00871 cursor+=userDomainSize;
00872 }
00873 strcpy(cursor,key->key+userSize);
00874 } else strcpy(cursor,key->key);
00875
00876 return length;
00877 }
00878
00879
00880
00881
00882
00894 int keyNameGetNamespace(const char *keyName) {
00895 if (keyNameIsSystem(keyName)) return KEY_NS_SYSTEM;
00896 if (keyNameIsUser(keyName)) return KEY_NS_USER;
00897 return 0;
00898 }
00899
00900
00901
00912 int keyGetNamespace(const Key *key) {
00913
00914
00915
00916 if (key->flags & KEY_SWITCH_ISSYSTEM) return KEY_NS_SYSTEM;
00917 if (key->flags & KEY_SWITCH_ISUSER) return KEY_NS_USER;
00918 return 0;
00919 }
00920
00921
00922
00932 int keyNameIsSystem(const char *keyName) {
00933
00934
00935
00936 if (!strncmp("system",keyName,sizeof("system")-1)) return 1;
00937 return 0;
00938 }
00939
00940
00941
00950 int keyIsSystem(const Key *key) {
00951
00952
00953
00954 return (key->flags & KEY_SWITCH_ISSYSTEM)?1:0;
00955 }
00956
00957
00958
00968 int keyNameIsUser(const char *keyName) {
00969
00970
00971
00972 if (!strncmp("user",keyName,sizeof("user")-1)) return 1;
00973 return 0;
00974 }
00975
00976
00977
00986 int keyIsUser(const Key *key) {
00987
00988
00989
00990 return (key->flags & KEY_SWITCH_ISUSER)?1:0;
00991 }
00992
00993
00994
01005 ssize_t keyNameGetRootNameSize(const char *keyName) {
01006 char *end;
01007 int length=strlen(keyName);
01008
01009 if (!length) return 0;
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 end=strchr(keyName,RG_KEY_DELIM);
01022 if (!end)
01023 end = (char *)keyName + length;
01024
01025 return end-keyName;
01026 }
01027
01028
01029
01040 ssize_t keyGetRootNameSize(const Key *key) {
01041
01042
01043 if (!key->key) return 0;
01044
01045 return keyNameGetRootNameSize(key->key);
01046 }
01047
01048
01049
01067 ssize_t keyGetRootName(const Key *key, char *returned, size_t maxSize) {
01068 size_t size;
01069
01070
01071
01072
01073
01074
01075 if (!key->key) {
01076 errno=KDB_RET_NOKEY;
01077 return -1;
01078 }
01079
01080 if (!(size=keyGetRootNameSize(key))) {
01081 errno=KDB_RET_NOKEY;
01082 return -1;
01083 }
01084
01085 if (maxSize < size) {
01086 errno=KDB_RET_TRUNC;
01087 return -1;
01088 } else strncpy(returned,key->key,size);
01089 return size;
01090 }
01091
01092
01093
01105 ssize_t keyGetFullRootNameSize(const Key *key) {
01106 size_t size=0;
01107
01108 if (keyIsUser(key)) {
01109 if (key->userDomain) size=strblen(key->userDomain);
01110 else size=strblen(getenv("USER"));
01111 }
01112
01113 return size+keyNameGetRootNameSize(key->key);
01114 }
01115
01116
01134 ssize_t keyGetFullRootName(const Key *key, char *returned, size_t maxSize) {
01135 size_t size;
01136 size_t userSize;
01137 char *cursor;
01138
01139
01140
01141
01142
01143
01144 if (!key->key) {
01145 errno=KDB_RET_NOKEY;
01146 return 0;
01147 }
01148
01149 if (!(size=keyGetFullRootNameSize(key))) {
01150 errno=KDB_RET_NOKEY;
01151 return 0;
01152 }
01153
01154 if (maxSize < size) {
01155 errno=KDB_RET_TRUNC;
01156 return -1;
01157 }
01158
01159 userSize = keyGetRootNameSize(key);
01160 strncpy(returned,key->key, userSize);
01161 if (keyIsUser(key)) {
01162 cursor = returned + userSize;
01163 *cursor = ':'; cursor++;
01164 if (key->userDomain)
01165 strncpy (cursor, key->userDomain, size - userSize);
01166 else
01167 strncpy (cursor, getenv("USER"), size - userSize);
01168 }
01169
01170 return size;
01171 }
01172
01173
01174
01175
01176
01177
01185 ssize_t keyGetParentNameSize(const Key *key) {
01186 char *parentNameEnd;
01187
01188
01189
01190
01191
01192
01193 if (!key->key) {
01194 errno=KDB_RET_NOKEY;
01195 return 0;
01196 }
01197
01198
01199
01200
01201
01202
01203
01204 parentNameEnd=strrchr(key->key,RG_KEY_DELIM);
01205
01206 if (!parentNameEnd || parentNameEnd==key->key) {
01207
01208 return 0;
01209 }
01210
01211
01212 if ((parentNameEnd-key->key) == (strblen(key->key)-2)) {
01213 parentNameEnd--;
01214 while (*parentNameEnd!=RG_KEY_DELIM) parentNameEnd--;
01215 }
01216
01217 return parentNameEnd - key->key;
01218 }
01219
01220
01221
01240 ssize_t keyGetParentName(const Key *key, char *returnedParent, size_t maxSize) {
01241 ssize_t parentSize;
01242
01243 parentSize=keyGetParentNameSize(key);
01244
01245 if (parentSize+1 > maxSize) {
01246 errno=KDB_RET_TRUNC;
01247 return 0;
01248 } else strncpy(returnedParent,key->key,parentSize);
01249
01250 returnedParent[parentSize]=0;
01251
01252 return parentSize;
01253 }
01254
01255
01256
01257
01258
01259
01274 ssize_t keyNameGetBaseNameSize(const char *keyName) {
01275 char *end;
01276
01277 end=strrchr(keyName,RG_KEY_DELIM);
01278 if (end) return keyName+strblen(keyName)-1-end;
01279 else return 0;
01280 }
01281
01282
01283
01298 ssize_t keyGetBaseNameSize(const Key *key) {
01299
01300
01301 if (!key->key) return 0;
01302
01303 return keyNameGetBaseNameSize(key->key);
01304 }
01305
01306
01307
01322 ssize_t keyGetBaseName(const Key *key, char *returned, size_t maxSize) {
01323 ssize_t size;
01324 size_t keySize;
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336 if (!(size=keyGetBaseNameSize(key))) {
01337 errno=KDB_RET_NOKEY;
01338 return 0;
01339 }
01340
01341 keySize=strblen(key->key);
01342
01343 if (maxSize < size) {
01344 strncpy(returned,key->key+keySize-size,maxSize);
01345 errno=KDB_RET_TRUNC;
01346 return size;
01347 } else strncpy(returned,key->key+keySize-size,size);
01348
01349 return size;
01350 }
01351
01352
01362 char *keyStealBaseName(const Key *key) {
01363 char *end=strrchr(key->key,RG_KEY_DELIM);
01364
01365 if (++end) return end;
01366 else return 0;
01367 }
01368
01369
01370
01371
01372
01373
01374
01375
01376
01382 ssize_t keyGetDataSize(const Key *key) {
01383 return keyGetValueSize(key);
01384 }
01385
01386
01387
01398 ssize_t keyGetValueSize(const Key *key) {
01399
01400
01401
01402
01403
01404 return key->dataSize;
01405 }
01406
01407
01408
01426 ssize_t keySetString(Key *key, const char *newStringValue) {
01427 ssize_t ret=newStringValue?strblen(newStringValue):0;
01428
01429 if (!newStringValue || !ret) ret=keySetRaw(key,0,0);
01430 else ret=keySetRaw(key,newStringValue,ret);
01431
01432 keySetType(key,KEY_TYPE_STRING);
01433
01434 return ret;
01435 }
01436
01437
01438
01463 ssize_t keyGetString(const Key *key, char *returnedString, size_t maxSize) {
01464
01465
01466
01467
01468
01469 if (!key->data) {
01470 *returnedString=0;
01471 errno=KDB_RET_NODATA;
01472 return 0;
01473 }
01474
01475 if (key->dataSize > maxSize) {
01476 errno=KDB_RET_TRUNC;
01477 return -1;
01478 }
01479
01480 if (key->type < KEY_TYPE_STRING) {
01481 errno=KDB_RET_TYPEMISMATCH;
01482 return -1;
01483 }
01484
01485 strcpy(returnedString,key->data);
01486 return key->dataSize;
01487 }
01488
01489
01490
01491
01492
01493
01543 void *keyStealValue(const Key *key) {
01544 return key->data;
01545 }
01546
01547
01548
01549
01550
01551
01552
01553
01563 ssize_t keySetLink(Key *key, const char *target) {
01564 ssize_t ret=target?strblen(target):0;
01565
01566 if (!target || !ret) ret=keySetRaw(key,0,0);
01567 else ret=keySetRaw(key,target,ret);
01568
01569 keySetType(key,KEY_TYPE_LINK);
01570
01571 return ret;
01572 }
01573
01574
01575
01586 ssize_t keyGetLink(const Key *key, char *returnedTarget, size_t maxSize) {
01590
01591
01592
01593
01594
01595 if (!key->data) {
01596 errno=KDB_RET_NODATA;
01597 return 0;
01598 }
01599
01600 if (key->type != KEY_TYPE_LINK) {
01601 errno=KDB_RET_TYPEMISMATCH;
01602 return -1;
01603 }
01604
01605 if (key->dataSize > maxSize) {
01606 errno=KDB_RET_TRUNC;
01607 return -1;
01608 }
01609
01610 strcpy(returnedTarget,key->data);
01611 return key->dataSize;
01612 }
01613
01614
01615
01625 int keyIsLink(const Key *key) {
01626
01627
01628
01629
01630 return (key->type==KEY_TYPE_LINK);
01631 }
01632
01633
01634
01644 int keyIsDir(const Key *key) {
01645
01646
01647
01648 return key->type==KEY_TYPE_DIR;
01649 }
01650
01651
01652
01660 int keyIsBin(const Key *key) {
01661
01662
01663
01664 return (KEY_TYPE_BINARY <= key->type && key->type < KEY_TYPE_STRING);
01665 }
01666
01667
01675 int keyIsString(const Key *key) {
01676
01677
01678
01679 return (key->type >= KEY_TYPE_STRING);
01680 }
01681
01682
01683
01684
01694 ssize_t keyGetBinary(const Key *key, void *returnedValue, size_t maxSize) {
01695
01696
01697
01698
01699
01700 if (!key->data) {
01701 errno=KDB_RET_NODATA;
01702 return 0;
01703 }
01704
01705 if (key->dataSize > maxSize) {
01706 errno=KDB_RET_TRUNC;
01707 return -1;
01708 }
01709
01710 memcpy(returnedValue,key->data,key->dataSize);
01711 return key->dataSize;
01712 }
01713
01714
01715
01735 ssize_t keySetBinary(Key *key, const void *newBinary, size_t dataSize) {
01736 ssize_t ret=keySetRaw(key,newBinary,dataSize);
01737
01738 keySetType(key,KEY_TYPE_BINARY);
01739
01740 return ret;
01741 }
01742
01743
01744
01753 int keyNeedsSync(const Key *key) {
01754
01755 return (key->flags & KEY_SWITCH_NEEDSYNC);
01756 }
01757
01758
01759
01769 uint8_t keyGetType(const Key *key) {
01770
01771
01772
01773
01774
01775 return key->type;
01776 }
01777
01778
01779
01848 uint8_t keySetType(Key *key,uint8_t newType) {
01849 mode_t dirSwitch=0111;
01850
01851
01852
01853
01854
01855
01856
01857 switch (newType) {
01858 case KEY_TYPE_DIR:
01859 key->type=KEY_TYPE_DIR;
01860 dirSwitch=umask(0); umask(dirSwitch);
01861 dirSwitch=0111 & ~dirSwitch;
01862 key->access|=dirSwitch | 0040000;
01863 keySetRaw(key,0,0);
01864 break;
01865 default:
01866 key->type=newType;
01867 key->access &= ~(0040000 | dirSwitch);
01868
01869 key->flags |= KEY_SWITCH_NEEDSYNC;
01870 }
01871 return key->type;
01872 }
01873
01874
01875
01888 ssize_t keySetRaw(Key *key, const void *newBinary, size_t dataSize) {
01889
01890
01891
01892
01893
01894
01895 if (!dataSize || !newBinary) {
01896 if (key->data) {
01897 free(key->data);
01898 key->data=0;
01899 }
01900 key->flags &= ~(KEY_SWITCH_VALUE);
01901 key->flags |= KEY_SWITCH_NEEDSYNC;
01902 return 0;
01903 }
01904
01905 key->dataSize=dataSize;
01906 if (key->data) {
01907 char *p;
01908 p=realloc(key->data,key->dataSize);
01909 if (NULL==p) return -1;
01910 key->data=p;
01911 } else {
01912 key->data=malloc(key->dataSize);
01913 }
01914
01915 if (!key->data) return -1;
01916
01917 memcpy(key->data,newBinary,key->dataSize);
01918 key->flags |= KEY_SWITCH_VALUE | KEY_SWITCH_NEEDSYNC;
01919 return key->dataSize;
01920 }
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01946 ssize_t keySetOwner(Key *key, const char *userDomain) {
01947 ssize_t size;
01948
01949
01950
01951
01952
01953
01954
01955 if (userDomain == 0) {
01956 if (key->userDomain) {
01957 free(key->userDomain);
01958 key->userDomain=0;
01959 }
01960 return 0;
01961 }
01962
01963 if ((size=strblen(userDomain)) > 0) {
01964 if (key->userDomain) {
01965 char *p;
01966 p=realloc(key->userDomain,size);
01967 if (NULL==p) {
01968 errno=KDB_RET_NOMEM;
01969 return -1;
01970 }
01971 key->userDomain=p;
01972 } else {
01973 key->userDomain=malloc(size);
01974 }
01975 if (!key->userDomain) return -1;
01976
01977 strcpy(key->userDomain,userDomain);
01978 key->flags |= KEY_SWITCH_DOMAIN | KEY_SWITCH_NEEDSYNC;
01979 return size;
01980 } else if (key->userDomain) {
01981 free(key->userDomain);
01982 key->userDomain=0;
01983 key->flags &= ~(KEY_SWITCH_DOMAIN | KEY_SWITCH_NEEDSYNC);
01984 }
01985 return 0;
01986 }
01987
01988
01989
01997 ssize_t keyGetOwnerSize(const Key *key) {
01998
01999
02000
02001
02002
02003
02004 if (!key->userDomain) {
02005 errno=KDB_RET_NODOMAIN;
02006 return 0;
02007 }
02008
02009 return strblen(key->userDomain);
02010 }
02011
02012
02013
02034 ssize_t keyGetOwner(const Key *key, char *returned, size_t maxSize) {
02035 ssize_t bytes;
02036
02037
02038
02039
02040
02041
02042 if (!key->userDomain) {
02043 errno=KDB_RET_NODOMAIN;
02044 return 0;
02045 }
02046
02047 if (maxSize < (bytes=strblen(key->userDomain))) {
02048 errno=KDB_RET_TRUNC;
02049 return -1;
02050 } else strcpy(returned,key->userDomain);
02051 return bytes;
02052 }
02053
02054
02055
02056
02066 char *keyStealOwner(const Key *key) {
02067 return key->userDomain;
02068 }
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02092 ssize_t keySetComment(Key *key, const char *newComment) {
02093 ssize_t size;
02094
02095
02096
02097
02098
02099
02100
02101 if (newComment && (size=strblen(newComment)) > 0) {
02102 if (key->flags & KEY_SWITCH_COMMENT) {
02103 char *p;
02104 p=realloc(key->comment,size);
02105 if (NULL==p) {
02106 errno=KDB_RET_NOMEM;
02107 return -1;
02108 }
02109 key->comment=p;
02110 } else {
02111 key->comment=malloc(size);
02112 }
02113 if (!key->comment) return -1;
02114
02115 strcpy(key->comment,newComment);
02116 key->flags |= KEY_SWITCH_COMMENT | KEY_SWITCH_NEEDSYNC;
02117 return key->commentSize=size;
02118 } else if (key->flags & KEY_SWITCH_COMMENT) {
02119 free(key->comment);
02120 key->comment=0;
02121 key->flags &= ~(KEY_SWITCH_COMMENT | KEY_SWITCH_NEEDSYNC);
02122 }
02123 return key->commentSize=0;
02124 }
02125
02126
02127
02138 ssize_t keyGetCommentSize(const Key *key) {
02139
02140
02141
02142
02143
02144 if (!key->comment) {
02145 errno=KDB_RET_NODESC;
02146 return 0;
02147 }
02148
02149 return strblen(key->comment);
02150 }
02151
02152
02153
02165 ssize_t keyGetComment(const Key *key, char *returnedDesc, size_t maxSize) {
02166 ssize_t bytes;
02167
02168
02169
02170
02171
02172
02173 if (!key->comment) {
02174 errno=KDB_RET_NODESC;
02175 return 0;
02176 }
02177
02178 bytes=strblen(strncpy(returnedDesc,key->comment,maxSize));
02179 if (maxSize < strblen(key->comment)) {
02180 errno=KDB_RET_TRUNC;
02181 return -1;
02182 }
02183 return bytes;
02184 }
02185
02186
02197 char *keyStealComment(const Key *key) {
02198 return key->comment;
02199 }
02200
02201
02202
02203
02204
02205
02206 ssize_t keyGetRecordSize(const Key *key) {
02207
02208
02209
02210
02211
02212 return key->recordSize;
02213 }
02214
02215
02221 Key *keyNext(Key *key) {
02222 return key->next;
02223 }
02224
02225
02226
02227
02228
02229
02230
02231
02248 int keyDup(const Key *source, Key *dest) {
02249
02250
02251 *dest=*source;
02252
02253
02254 dest->key=
02255 dest->comment=
02256 dest->userDomain=
02257 dest->data=0;
02258
02259
02260 keySetName(dest,source->key);
02261 keySetComment(dest,source->comment);
02262 keySetOwner(dest,source->userDomain);
02263 keySetRaw(dest,source->data,source->dataSize);
02264
02265 dest->flags=source->flags;
02266
02267 return 0;
02268 }
02269
02270
02271
02282 uid_t keyGetUID(const Key *key) {
02283
02284
02285
02286
02287
02288
02289
02290 return key->uid;
02291 }
02292
02293
02294
02305 int keySetUID(Key *key, uid_t uid) {
02306
02307
02308
02309 key->uid=uid;
02310 key->flags |= KEY_SWITCH_UID | KEY_SWITCH_NEEDSYNC;
02311
02312 return 0;
02313 }
02314
02315
02316
02324 gid_t keyGetGID(const Key *key) {
02325
02326
02327
02328
02329
02330
02331
02332 return key->gid;
02333 }
02334
02335
02336
02344 int keySetGID(Key *key, gid_t gid) {
02345
02346
02347
02348 key->gid=gid;
02349 key->flags |= KEY_SWITCH_GID | KEY_SWITCH_NEEDSYNC;
02350
02351 return 0;
02352 }
02353
02354
02355
02361 mode_t keyGetAccess(const Key *key) {
02362
02363
02364
02365
02366
02367
02368
02369 return key->access;
02370 }
02371
02372
02373
02381 int keySetAccess(Key *key, mode_t mode) {
02382
02383
02384
02385 key->access=mode;
02386 key->flags |= KEY_SWITCH_MODE | KEY_SWITCH_NEEDSYNC;
02387
02388 return 0;
02389 }
02390
02391
02392
02397 time_t keyGetMTime(const Key *key) {
02398
02399
02400
02401
02402
02403
02404 return key->mtime;
02405 }
02406
02407
02408
02413 time_t keyGetATime(const Key *key) {
02414
02415
02416
02417
02418
02419
02420 return key->atime;
02421 }
02422
02423
02424
02429 time_t keyGetCTime(const Key *key) {
02430
02431
02432
02433
02434
02435
02436 return key->ctime;
02437 }
02438
02439
02440
02513 uint32_t keyCompare(const Key *key1, const Key *key2) {
02514 uint32_t ret=0;
02515
02516
02517
02518 if (key1->uid != key2->uid) ret|=KEY_SWITCH_UID;
02519 if (key1->gid != key2->gid) ret|=KEY_SWITCH_GID;
02520 if (key1->type != key2->type) ret|=KEY_SWITCH_TYPE;
02521 #if defined(S_IRWXU) && defined(S_IRWXG) && defined(S_IRWXO)
02522 if ((key1->access & (S_IRWXU|S_IRWXG|S_IRWXO)) !=
02523 (key2->access & (S_IRWXU|S_IRWXG|S_IRWXO))) ret|=KEY_SWITCH_MODE;
02524 #else
02525 if ((key1->access) !=
02526 (key2->access)) ret|=KEY_SWITCH_MODE;
02527 #endif
02528
02529
02530
02531 if (key1->key && key2->key) {
02532 if (strcmp(key1->key,key2->key)) ret|=KEY_SWITCH_NAME;
02533 } else {
02534 if (key1->key) ret|=KEY_SWITCH_NAME;
02535 else if (key2->key) ret|=KEY_SWITCH_NAME;
02536 }
02537
02538 if (key1->comment && key2->comment) {
02539 if (strcmp(key1->comment,key2->comment)) ret|=KEY_SWITCH_COMMENT;
02540 } else {
02541 if (key1->comment) ret|=KEY_SWITCH_COMMENT;
02542 else if (key2->comment) ret|=KEY_SWITCH_COMMENT;
02543 }
02544
02545 if (key1->userDomain && key2->userDomain) {
02546 if (strcmp(key1->userDomain,key2->userDomain)) ret|=KEY_SWITCH_DOMAIN;
02547 } else {
02548 if (key1->userDomain) ret|=KEY_SWITCH_DOMAIN;
02549 else if (key2->comment) ret|=KEY_SWITCH_DOMAIN;
02550 }
02551
02552
02553 ret|=(key1->flags ^ key2->flags) & (KEY_SWITCH_FLAG | KEY_SWITCH_NEEDSYNC);
02554
02555
02556 if (key1->dataSize != key2->dataSize) ret|=KEY_SWITCH_VALUE;
02557 else if (memcmp(key1->data,key2->data,
02558 (key1->dataSize<=key2->dataSize?key1->dataSize:key2->dataSize)))
02559 ret|=KEY_SWITCH_VALUE;
02560
02561 return ret;
02562 }
02563
02564
02565
02566
02567
02568
02603 ssize_t keyToStream(const Key *key, FILE* stream, unsigned long options) {
02604 return keyToStreamBasename(key,stream,0,0,options);
02605 }
02606
02607
02608
02609
02610
02633 ssize_t keyToStreamBasename(const Key *key, FILE *stream, const char *parent,
02634 const size_t parentSize, unsigned long options) {
02635 ssize_t written=0;
02636 char buffer[800];
02637 struct passwd *pwd=0;
02638 struct group *grp=0;
02639
02640
02641 if (parent) {
02642
02643 int found;
02644 size_t skip=parentSize ? parentSize : strblen(parent)-1;
02645
02646 found=memcmp(parent,key->key,skip);
02647 if (found == 0) {
02648 while (*(key->key+skip) == RG_KEY_DELIM) ++skip;
02649
02650 if (*(key->key+skip) != 0)
02651 written+=fprintf(stream,"<key basename=\"%s\"",
02652 key->key+skip);
02653 }
02654 }
02655
02656 if (written == 0) {
02657 if (options & KDB_O_FULLNAME) {
02658 keyGetFullName(key,buffer,sizeof(buffer));
02659 written+=fprintf(stream,"<key name=\"%s\"", buffer);
02660 } else written+=fprintf(stream,"<key name=\"%s\"", key->key);
02661 }
02662
02663
02664 if (options & KDB_O_CONDENSED) written+=fprintf(stream," ");
02665 else written+=fprintf(stream,"\n ");
02666
02667
02668
02669
02670 if (options & KDB_O_NUMBERS) {
02671 written+=fprintf(stream,"type=\"%d\"", key->type);
02672 } else {
02673 buffer[0]=0;
02674
02675 switch (key->type) {
02676 case KEY_TYPE_STRING:
02677 strcpy(buffer,"string");
02678 break;
02679 case KEY_TYPE_BINARY:
02680 strcpy(buffer,"binary");
02681 break;
02682 case KEY_TYPE_LINK:
02683 strcpy(buffer,"link");
02684 break;
02685 case KEY_TYPE_DIR:
02686 strcpy(buffer,"directory");
02687 break;
02688 case KEY_TYPE_UNDEFINED:
02689 strcpy(buffer,"undefined");
02690 break;
02691 }
02692 if (buffer[0]) written+=fprintf(stream,"type=\"%s\"", buffer);
02693 else written+=fprintf(stream,"type=\"%d\"", key->type);
02694 }
02695
02696 #ifdef HAVE_PWD_H
02697 if (keyIsUser(key)) {
02698 struct passwd *domainPwd=0;
02699 int uidMatch,gidMatch;
02700
02701 domainPwd=getpwnam(key->userDomain);
02702 pwd=getpwuid(key->uid);
02703 grp=getgrgid(key->gid);
02704
02705 uidMatch=(key->uid == domainPwd->pw_uid);
02706 gidMatch=(key->gid == domainPwd->pw_gid);
02707
02708 if (options & KDB_O_FULLUGID) {
02709 if (pwd && !(options & KDB_O_NUMBERS))
02710 written+=fprintf(stream," uid=\"%s\"",pwd->pw_name);
02711 else written+=fprintf(stream, " uid=\"%d\"",key->uid);
02712
02713 if (grp && !(options & KDB_O_NUMBERS))
02714 written+=fprintf(stream," gid=\"%s\"",grp->gr_name);
02715 else written+=fprintf(stream," gid=\"%d\"",key->gid);
02716 } else {
02717 if (!uidMatch) {
02718 if (pwd && !(options & KDB_O_NUMBERS))
02719 written+=fprintf(stream," uid=\"%s\"",pwd->pw_name);
02720 else written+=fprintf(stream, " uid=\"%d\"",key->uid);
02721 }
02722
02723 if (!gidMatch) {
02724 if (grp && !(options & KDB_O_NUMBERS))
02725 written+=fprintf(stream," gid=\"%s\"",grp->gr_name);
02726 else written+=fprintf(stream, " gid=\"%d\"",key->gid);
02727 }
02728 }
02729 } else {
02730 if (!(options & KDB_O_NUMBERS)) {
02731 pwd=getpwuid(key->uid);
02732 grp=getgrgid(key->gid);
02733 }
02734
02735
02736 if (pwd) written+=fprintf(stream," uid=\"%s\"",pwd->pw_name);
02737 else written+=fprintf(stream, " uid=\"%d\"",key->uid);
02738
02739 if (grp) written+=fprintf(stream," gid=\"%s\"",grp->gr_name);
02740 else written+=fprintf(stream, " gid=\"%d\"",key->gid);
02741 }
02742 #endif
02743 written+=fprintf(stream," mode=\"0%o\"",
02744 #if defined(S_IRWXU) && defined(S_IRWXG) && defined(S_IRWXO)
02745 key->access & (S_IRWXU|S_IRWXG|S_IRWXO));
02746 #else
02747 key->access);
02748 #endif
02749
02750
02751 if (!key->data && !key->comment) {
02752 written+=fprintf(stream,"/>");
02753 if (!(options & KDB_O_CONDENSED))
02754 written+=fprintf(stream,"\n\n\n\n\n\n");
02755
02756 return written;
02757 } else {
02758 if (key->data) {
02759 if ((key->dataSize <= 16) &&
02760 key->type >= KEY_TYPE_STRING &&
02761 !strchr(key->data,'\n')) {
02762
02763
02764
02765
02766
02767 if (options & KDB_O_CONDENSED) written+=fprintf(stream," ");
02768 else written+=fprintf(stream,"\n ");
02769
02770 written+=fprintf(stream,"value=\"%s\"",key->data);
02771
02772 if (key->comment) written+=fprintf(stream,">\n");
02773 else {
02774 written+=fprintf(stream,"/>");
02775 if (!(options & KDB_O_CONDENSED))
02776 written+=fprintf(stream,"\n\n\n\n\n\n");
02777
02778 return written;
02779 }
02780 } else {
02781 written+=fprintf(stream,">");
02782 if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n\n ");
02783
02784 written+=fprintf(stream,"<value>");
02785 if (key->type >= KEY_TYPE_STRING || key->type < KEY_TYPE_BINARY) {
02786 written+=fprintf(stream,"<![CDATA[");
02787 fflush(stream);
02788
02789 written+=write(fileno(stream),key->data,key->dataSize-1);
02790 written+=fprintf(stream,"]]>");
02791 } else {
02792
02793 char *encoded=malloc(3*key->dataSize);
02794 size_t encodedSize;
02795
02796 written+=fprintf(stream,"\n");
02797 encodedSize=encode(key->data,key->dataSize,encoded);
02798 fflush(stream);
02799 written+=write(fileno(stream),encoded,encodedSize);
02800 free(encoded);
02801 written+=fprintf(stream,"\n");
02802 }
02803
02804 written+=fprintf(stream,"</value>");
02805 }
02806 } else {
02807 if (key->comment) {
02808 written+=fprintf(stream,">");
02809 if (!(options & KDB_O_CONDENSED))
02810 written+=fprintf(stream,"\n");
02811 } else {
02812 written+=fprintf(stream,"/>");
02813 if (!(options & KDB_O_CONDENSED))
02814 written+=fprintf(stream,"\n\n\n\n\n\n");
02815
02816 return written;
02817 }
02818 }
02819 }
02820
02821 if (!(options & KDB_O_CONDENSED)) {
02822 written+=fprintf(stream,"\n");
02823 if (key->comment) written+=fprintf(stream," ");
02824 }
02825
02826 if (key->comment) {
02827 written+=fprintf(stream,"<comment><![CDATA[%s]]></comment>", key->comment);
02828 if (!(options & KDB_O_CONDENSED))
02829 written+=fprintf(stream,"\n");
02830 }
02831
02832 written+=fprintf(stream,"</key>");
02833
02834 if (!(options & KDB_O_CONDENSED))
02835 written+=fprintf(stream,"\n\n\n\n\n\n");
02836
02837 return written;
02838 }
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02875 int keySetFlag(Key *key) {
02876
02877
02878
02879
02880
02881 key->flags|=KEY_SWITCH_FLAG;
02882
02883 return 0;
02884 }
02885
02886
02887
02899 int keyClearFlag(Key *key) {
02900
02901
02902
02903
02904
02905 key->flags &= ~KEY_SWITCH_FLAG;
02906
02907 return 0;
02908 }
02909
02910
02911
02924 int keyGetFlag(const Key *key) {
02925
02926
02927
02928
02929
02930 return (key->flags & KEY_SWITCH_FLAG) ? 1:0;
02931 }
02932
02933
02934
02935
02936
02973 int keyInit(Key *key) {
02974
02975
02976 memset(key,0,sizeof(Key));
02977 key->type=KEY_TYPE_UNDEFINED;
02978
02979 #if defined(HAVE_GETUID) && defined(HAVE_GETGID)
02980 key->uid=getuid();
02981 key->gid=getgid();
02982 #endif
02983 key->access=umask(0);
02984 umask(key->access);
02985 key->access=DEFFILEMODE & ~key->access;
02986
02987 key->flags = KEY_SWITCH_INITIALIZED;
02988
02989 return 0;
02990 }
02991
02992
02993
02994
03015 int keyClose(Key *key) {
03016
03017
03018
03019 if (key->key) free(key->key);
03020 if (key->data) free(key->data);
03021 if (key->comment) free(key->comment);
03022 if (key->userDomain) free(key->userDomain);
03023 memset(key,0,sizeof(Key));
03024 return 0;
03025 }
03026