00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "kdb.h"
00041 #include "kdbprivate.h"
00042
00043
00044 #include <sys/types.h>
00045 #include <sys/stat.h>
00046 #include <fcntl.h>
00047 #include <stdlib.h>
00048 #include <unistd.h>
00049 #include <pwd.h>
00050 #include <dirent.h>
00051 #include <errno.h>
00052 #include <stdio.h>
00053 #include <iconv.h>
00054 #include <locale.h>
00055 #include <langinfo.h>
00056 #include <ctype.h>
00057 #include <string.h>
00058 #include <utmp.h>
00059
00060
00061 #define UTF8_TO 1
00062 #define UTF8_FROM 0
00063
00064 #define BUFFER_SIZE 100
00065
00066 #ifdef UT_NAMESIZE
00067 #define USER_NAME_SIZE UT_NAMESIZE
00068 #else
00069 #define USER_NAME_SIZE 100
00070 #endif
00071
00073 #ifdef PATH_MAX
00074 #define MAX_PATH_LENGTH PATH_MAX
00075
00076 #elif __USE_POSIX
00077 #define MAX_PATH_LENGTH _POSIX_PATH_MAX
00078 #else
00079 #define MAX_PATH_LENGTH 4096
00080 #endif
00081
00082
00083 extern int errno;
00084
00085
00086
00087
00117
00118
00119
00120
00121
00122
00123
00124
00136 int kdbOpen() {
00137
00138 setlocale(LC_ALL,"");
00139
00140 return 0;
00141 }
00142
00153 int kdbClose() {
00154 return 0;
00155 }
00156
00167 size_t keyGetSerializedSize(const Key *key) {
00168 size_t size,tmp;
00169
00170
00171 size=5+sizeof(u_int8_t)+1;
00172 if (key->comment) size+=strblen(key->comment);
00173 size++;
00174 tmp=keyGetDataSize(key);
00175 size+=tmp;
00176 return size;
00177 }
00178
00190 size_t unencode(char *encoded,void *returned) {
00191 char byteInHexa[5]="0x";
00192 char *readCursor=encoded;
00193 char *writeCursor=returned;
00194
00195 if (!encoded) {
00196 if (returned) *(char *)returned=0;
00197 return 0;
00198 }
00199
00200 byteInHexa[4]=0;
00201 while (*readCursor) {
00202 if (isspace((int)*readCursor))
00203 {
00204 readCursor++;
00205 continue;
00206 }
00207 if (isxdigit((int)*readCursor)) {
00208 long int converted;
00209 byteInHexa[2]=readCursor[0];
00210 byteInHexa[3]=readCursor[1];
00211 converted=strtol(byteInHexa,0,16);
00212 *writeCursor=(unsigned char)converted;
00213
00214 readCursor+=2;
00215 writeCursor++;
00216 } else {
00217
00218 errno=KDB_RET_TYPEMISMATCH;
00219 return 0;
00220 }
00221 }
00222 return (long int)writeCursor-(long int)returned;
00223 }
00224
00231 int kdbNeedsUTF8Conversion() {
00232 return strcmp(nl_langinfo(CODESET),"UTF-8");
00233 }
00234
00235
00245 int UTF8Engine(int direction, char **string, size_t *inputByteSize) {
00246 char *currentCharset=0;
00247 char *converted=0;
00248 char *readCursor, *writeCursor;
00249 size_t bufferSize;
00250 iconv_t converter;
00251
00252 if (kdbNeedsUTF8Conversion()) currentCharset=nl_langinfo(CODESET);
00253 else return 0;
00254
00255 if (direction==UTF8_TO) converter=iconv_open("UTF-8",currentCharset);
00256 else converter=iconv_open(currentCharset,"UTF-8");
00257
00258 if (converter == (iconv_t)(-1)) return -1;
00259
00260
00261 bufferSize=*inputByteSize * 4;
00262 converted=malloc(bufferSize);
00263 if (!converted) return -1;
00264
00265 readCursor=*string;
00266 writeCursor=converted;
00267 if (iconv(converter,
00268 &readCursor,inputByteSize,
00269 &writeCursor,&bufferSize) == (size_t)(-1)) {
00270 free(converted);
00271 iconv_close(converter);
00272 return -1;
00273 }
00274
00275
00276 *inputByteSize=writeCursor-converted;
00277
00278 readCursor=*string;
00279
00280 *string=malloc(*inputByteSize);
00281
00282 memcpy(*string,converted,*inputByteSize);
00283
00284 free(readCursor);
00285
00286 free(converted);
00287
00288 iconv_close(converter);
00289
00290 return 0;
00291 }
00292
00293
00294
00295
00302 int handleOldKeyFileVersion(Key *key,FILE *input,u_int16_t nversion) {
00303 char generalBuffer[BUFFER_SIZE];
00304 size_t currentBufferSize;
00305
00306 char type[5];
00307 char *data=0;
00308 size_t dataSize=0;
00309 char *comment=0;
00310 size_t commentSize=0;
00311
00312 int readComment=1;
00313 int eof=0;
00314
00315
00316
00317
00318
00319
00320
00321
00322 switch (nversion) {
00323 case 1: {
00324 if (!fgets(type, sizeof(type), input)) return -1;
00325
00326 while (readComment) {
00327 if (fgets(generalBuffer,sizeof(generalBuffer),input)) {
00328 if (memcmp(generalBuffer,"<DATA>\n\0",8)) {
00329
00330 currentBufferSize=strblen(generalBuffer);
00331 if (!comment) {
00332 comment=(char *)malloc(commentSize=currentBufferSize);
00333 strcpy(comment,generalBuffer);
00334 } else {
00335 char *buffer=0;
00336
00337 buffer=malloc(commentSize+currentBufferSize);
00338 strcpy(buffer,comment);
00339 strcat(buffer,generalBuffer);
00340 comment=realloc(comment,commentSize+=currentBufferSize);
00341 strcpy(comment,buffer);
00342 free(buffer);
00343 }
00344 } else readComment=0;
00345 } else {
00346 readComment=0;
00347 eof=1;
00348 }
00349 }
00350
00351
00352 if (commentSize > 1 && (*(comment+commentSize-2) == '\n')) {
00353 *(comment+commentSize-2)=0;
00354 --commentSize;
00355 }
00356
00357
00358 if (comment && UTF8Engine(UTF8_FROM,&comment,&commentSize)) {
00359 free(comment);
00360 return -1;
00361 }
00362
00363
00364 if (!eof) {
00365 while (fgets(generalBuffer,sizeof(generalBuffer),input)) {
00366 currentBufferSize=strlen(generalBuffer);
00367 if (!data) {
00368 data=(char *)malloc(dataSize=(currentBufferSize+1));
00369 strcpy(data,generalBuffer);
00370 } else {
00371 char *buffer=0;
00372
00373 buffer=malloc(dataSize+currentBufferSize);
00374 strcpy(buffer,data);
00375 strcat(buffer,generalBuffer);
00376 data=realloc(data,dataSize+=currentBufferSize);
00377 strcpy(data,buffer);
00378 free(buffer);
00379 }
00380 }
00381 }
00382
00383
00384 keySetComment(key,comment);
00385 if (comment) free(comment);
00386
00387
00388
00389 {
00390 u_int8_t oldVersion=atoi(type);
00391 switch (oldVersion) {
00392 case 1: keySetType(key,KEY_TYPE_BINARY); break;
00393 case 2: keySetType(key,KEY_TYPE_STRING); break;
00394 default: keySetType(key,oldVersion);
00395 }
00396 }
00397 if (!dataSize) {
00398 keySetRaw(key,0,0);
00399 return 0;
00400 }
00401
00402 if (keyGetType(key) <= KEY_TYPE_BINARY) {
00403
00404 char *unencoded=0;
00405 size_t unencodedSize;
00406
00407
00408 unencodedSize=dataSize/2;
00409
00410 unencoded=malloc(unencodedSize);
00411 if (!(unencodedSize=unencode(data,unencoded))) return -1;
00412 keySetRaw(key,unencoded,unencodedSize);
00413 free(unencoded);
00414 } else {
00415 if (UTF8Engine(UTF8_FROM,&data,&dataSize)) {
00416 free(data);
00417 return -1;
00418 }
00419 keySetRaw(key,data,dataSize);
00420 }
00421
00422 free(data);
00423
00424 return 0;
00425 }
00426 }
00427 return -1;
00428 }
00429
00430
00431
00432
00433
00442 int keyFileUnserialize(Key *key,FILE *input) {
00443 char generalBuffer[BUFFER_SIZE];
00444 size_t currentBufferSize;
00445
00446 char version[10];
00447 u_int16_t nversion=0;
00448 char type[5];
00449 char *data=0;
00450 size_t dataSize=0;
00451 char *comment=0;
00452 size_t commentSize=0;
00453
00454 int readComment=1;
00455 int eof=0;
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 if (!fgets(version, sizeof(version), input)) return -1;
00468 if (strncmp(version,"RG",2)) {
00469
00470 errno=KDB_RET_INVALIDKEY;
00471 return -1;
00472 }
00473
00474 nversion=atoi(version+2);
00475 if (!nversion || nversion > RG_KEY_FORMAT_VERSION) {
00476 errno=KDB_RET_INVALIDKEY;
00477 return -1;
00478 }
00479
00480 if (nversion != RG_KEY_FORMAT_VERSION)
00481 return handleOldKeyFileVersion(key,input,nversion);
00482
00483 if (!fgets(type, sizeof(type), input)) return -1;
00484
00485 while (readComment) {
00486 if (fgets(generalBuffer,sizeof(generalBuffer),input)) {
00487 if (memcmp(generalBuffer,"<DATA>\n\0",8)) {
00488
00489 currentBufferSize=strblen(generalBuffer);
00490 if (!comment) {
00491 comment=(char *)malloc(commentSize=currentBufferSize);
00492 strcpy(comment,generalBuffer);
00493 } else {
00494 char *buffer=0;
00495
00496 buffer=malloc(commentSize+currentBufferSize);
00497 strcpy(buffer,comment);
00498 strcat(buffer,generalBuffer);
00499 comment=realloc(comment,commentSize+=currentBufferSize);
00500 strcpy(comment,buffer);
00501 free(buffer);
00502 }
00503 } else readComment=0;
00504 } else {
00505 readComment=0;
00506 eof=1;
00507 }
00508 }
00509
00510
00511 if (commentSize > 1 && (*(comment+commentSize-2) == '\n')) {
00512 *(comment+commentSize-2)=0;
00513 --commentSize;
00514 }
00515
00516 if (comment && UTF8Engine(UTF8_FROM,&comment,&commentSize)) {
00517 free(comment);
00518 return -1;
00519 }
00520
00521
00522 if (!eof) {
00523 while (fgets(generalBuffer,sizeof(generalBuffer),input)) {
00524 currentBufferSize=strlen(generalBuffer);
00525 if (!data) {
00526 data=(char *)malloc(dataSize=(currentBufferSize+1));
00527 strcpy(data,generalBuffer);
00528 } else {
00529 char *buffer=0;
00530
00531 buffer=malloc(dataSize+currentBufferSize);
00532 strcpy(buffer,data);
00533 strcat(buffer,generalBuffer);
00534 data=realloc(data,dataSize+=currentBufferSize);
00535 strcpy(data,buffer);
00536 free(buffer);
00537 }
00538 }
00539 }
00540
00541
00542 keySetComment(key,comment);
00543 if (comment) free(comment);
00544 keySetType(key,atoi(type));
00545 if (!dataSize) {
00546 keySetRaw(key,0,0);
00547 return 0;
00548 }
00549
00550 if (keyGetType(key) <= KEY_TYPE_BINARY) {
00551
00552 char *unencoded=0;
00553 size_t unencodedSize;
00554
00555
00556 unencodedSize=dataSize/2;
00557
00558 unencoded=malloc(unencodedSize);
00559 if (!(unencodedSize=unencode(data,unencoded))) return -1;
00560 keySetRaw(key,unencoded,unencodedSize);
00561 free(unencoded);
00562 } else {
00563 if (UTF8Engine(UTF8_FROM,&data,&dataSize)) {
00564 free(data);
00565 return -1;
00566 }
00567 keySetRaw(key,data,dataSize);
00568 }
00569
00570 free(data);
00571
00572 return 0;
00573 }
00574
00575
00576
00591 size_t encode(void *unencoded, size_t size, char *returned) {
00592 void *readCursor=unencoded;
00593 void *writeCursor=returned;
00594 int blockStep=4;
00595 int lineStep=8*blockStep;
00596 int currentInBlock=0;
00597 int currentInLine=0;
00598
00599 while ((readCursor-unencoded)<size) {
00600 sprintf(writeCursor,"%02x",*(u_int8_t *)readCursor);
00601 readCursor++;
00602 writeCursor+=2;
00603 currentInBlock++;
00604 currentInLine++;
00605 if (currentInLine==lineStep) {
00606 *(char *)writeCursor='\n'; writeCursor++;
00607 currentInLine=0;
00608 currentInBlock=0;
00609 }
00610 if (currentInBlock==blockStep) {
00611 *(char *)writeCursor=' '; writeCursor++;
00612 currentInBlock=0;
00613 }
00614 }
00615 *(char *)writeCursor='\n';
00616 *(char *)++writeCursor=0;
00617 return (writeCursor)-(void *)returned;
00618 }
00619
00620
00621
00622
00623
00634 int keyFileSerialize(Key *key, FILE *output) {
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 size_t dataSize;
00646
00647 fprintf(output,"RG%03d\n",RG_KEY_FORMAT_VERSION);
00648 fprintf(output,"%d\n",key->type);
00649 if (key->comment) {
00650 if (kdbNeedsUTF8Conversion()) {
00651 size_t convertedCommentSize=key->commentSize;
00652 char *convertedComment=malloc(convertedCommentSize);
00653
00654 memcpy(convertedComment,key->comment,key->commentSize);
00655 if (UTF8Engine(UTF8_TO,&convertedComment,&convertedCommentSize)) {
00656 free(convertedComment);
00657 return -1;
00658 }
00659 fprintf(output,"%s\n",convertedComment);
00660 free(convertedComment);
00661 } else fprintf(output,"%s\n",key->comment);
00662 }
00663
00664 fputs("<DATA>\n",output);
00665 fflush(output);
00666
00667 dataSize=keyGetDataSize(key);
00668 if (dataSize) {
00669
00670 if (keyGetType(key) > KEY_TYPE_BINARY) {
00671 if (kdbNeedsUTF8Conversion()) {
00672 size_t convertedDataSize=key->dataSize;
00673 char *convertedData=malloc(convertedDataSize);
00674
00675 memcpy(convertedData,key->data,key->dataSize);
00676 if (UTF8Engine(UTF8_TO,&convertedData,&convertedDataSize)) {
00677 free(convertedData);
00678 return -1;
00679 }
00680 fprintf(output,"%s",convertedData);
00681 free(convertedData);
00682 } else fputs(key->data,output);
00683 } else {
00684 char *encoded=malloc(3*dataSize);
00685 size_t encodedSize;
00686
00687 encodedSize=encode(key->data,dataSize,encoded);
00688 fwrite(encoded,encodedSize,1,output);
00689 free(encoded);
00690 }
00691 }
00692 return 0;
00693 }
00694
00695
00705 size_t keyCalcRelativeFileName(Key *key,char *relativeFileName,size_t maxSize) {
00706 if (!key || !keyIsInitialized(key)) {
00707 errno=KDB_RET_UNINITIALIZED;
00708 return 0;
00709 }
00710 if (!key->key) {
00711 errno=KDB_RET_NOKEY;
00712 return 0;
00713 }
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 if (kdbNeedsUTF8Conversion()) {
00739 char *converted;
00740 size_t size;
00741
00742 if (!(size=keyGetNameSize(key))) return 0;
00743
00744 converted=malloc(size);
00745 keyGetName(key,converted,size);
00746
00747
00748
00749 if (UTF8Engine(UTF8_TO,&converted,&size)) {
00750 free(converted);
00751 return 0;
00752 }
00753
00754 if (size>maxSize) {
00755 free(converted);
00756 errno=E2BIG;
00757 return 0;
00758 }
00759
00760 memcpy(relativeFileName,converted,size);
00761 free(converted);
00762
00763 return size;
00764 } else return keyGetName(key,relativeFileName,maxSize);
00765
00766 return 0;
00767 }
00768
00769
00770
00771
00772
00773
00785 int keyFromStat(Key *key,struct stat *stat) {
00786 if (!key) {
00787 errno=KDB_RET_NULLKEY;
00788 return -1;
00789 }
00790
00791 keySetAccess(key,stat->st_mode);
00792 keySetUID(key,stat->st_uid);
00793 keySetGID(key,stat->st_gid);
00794 if (S_ISDIR(stat->st_mode)) keySetType(key,KEY_TYPE_DIR);
00795 key->atime=stat->st_atime;
00796 key->mtime=stat->st_mtime;
00797 key->ctime=stat->st_ctime;
00798 key->recordSize=stat->st_size;
00799 return 0;
00800 }
00801
00802
00803
00804
00814 size_t kdbGetFilename(Key *forKey,char *returned,size_t maxSize) {
00815 size_t length=0;
00816
00817 switch (keyGetNamespace(forKey)) {
00818 case KEY_NS_SYSTEM: {
00819
00820 strncpy(returned,RG_DB_SYSTEM,maxSize);
00821 length=strlen(returned);
00822 break;
00823 }
00824 case KEY_NS_USER: {
00825
00826 struct passwd *user=0;
00827 char userName[USER_NAME_SIZE];
00828
00829 length=keyGetOwner(forKey,userName,sizeof(userName));
00830 if (!length) strncpy(userName,getenv("USER"),sizeof(userName));
00831
00832 user=getpwnam(userName);
00833 if (!user) return 0;
00834 length=snprintf(returned,maxSize,"%s/%s",user->pw_dir,RG_DB_USER);
00835 break;
00836 }
00837 default: {
00838 errno=KDB_RET_INVALIDKEY;
00839 return 0;
00840 }
00841 }
00842
00843 returned[length]='/'; length++;
00844 length+=keyCalcRelativeFileName(forKey,returned+length,maxSize-length);
00845
00846 return length;
00847 }
00848
00849
00850
00867 int kdbGetValue(const char *keyname, char *returned,size_t maxSize) {
00868 Key key;
00869 int rc=0;
00870
00871 keyInit(&key);
00872 keySetName(&key,keyname);
00873 rc=kdbGetKey(&key);
00874 if (rc == 0) keyGetString(&key,returned,maxSize);
00875 else rc=errno;
00876 keyClose(&key);
00877 errno=rc;
00878 return rc;
00879 }
00880
00881
00882
00898 int kdbSetValue(const char *keyname, const char *value) {
00899 Key key;
00900 int rc;
00901
00902
00903 keySetName(&key,keyname);
00904 rc=kdbGetKey(&key);
00905 keySetString(&key,value);
00906 rc=kdbSetKey(&key);
00907 keyClose(&key);
00908 return rc;
00909 }
00910
00911
00912
00939 int kdbGetValueByParent(const char *parentName, const char *baseName, char *returned, size_t maxSize) {
00940 char name[strblen(parentName)+strblen(baseName)];
00941
00942 sprintf(name,"%s/%s",parentName,baseName);
00943 return kdbGetValue(name,returned,maxSize);
00944 }
00945
00946
00947
00957 int kdbSetValueByParent(const char *parentName, const char *baseName, const char *value) {
00958 char name[strblen(parentName)+strblen(baseName)];
00959
00960 sprintf(name,"%s/%s",parentName,baseName);
00961 return kdbSetValue(name,value);
00962 }
00963
00964
00965
00982 int kdbGetKeyByParent(const char *parentName, const char *baseName, Key *returned) {
00983 char name[strblen(parentName)+strblen(baseName)];
00984
00985 sprintf(name,"%s/%s",parentName,baseName);
00986 keySetName(returned,name);
00987
00988 return kdbGetKey(returned);
00989 }
00990
00991
01001 int kdbGetKeyByParentKey(const Key *parent, const char *baseName, Key *returned) {
01002 size_t size=keyGetFullNameSize(parent);
01003 char name[size+strblen(baseName)];
01004
01005 keyGetFullName(parent,name,size);
01006 name[size-1]='/';
01007 strcpy((char *)(name+size),baseName);
01008
01009 keySetName(returned,name);
01010
01011 return kdbGetKey(returned);
01012 }
01013
01014
01015
01016
01017
01018 int keyCompareByName(const void *p1, const void *p2) {
01019 Key *key1=*(Key **)p1;
01020 Key *key2=*(Key **)p2;
01021
01022 return strcmp(key1->key, key2->key);
01023 }
01024
01025
01026
01100 int kdbGetChildKeys(const char *parentName, KeySet *returned, unsigned long options) {
01101 char *realParentName=0;
01102 size_t parentNameSize;
01103 DIR *parentDir;
01104 Key parentKey;
01105 char buffer[MAX_PATH_LENGTH];
01106 struct dirent *entry;
01107
01108
01109
01110
01111
01112
01113 keyInit(&parentKey);
01114 keySetName(&parentKey,parentName);
01115 kdbGetFilename(&parentKey,buffer,sizeof(buffer));
01116 parentDir=opendir(buffer);
01117
01118
01119
01120 if (!parentDir) return -1;
01121
01122 parentNameSize=keyGetFullNameSize(&parentKey);
01123 realParentName=realloc(realParentName,parentNameSize);
01124 keyGetFullName(&parentKey,realParentName,parentNameSize);
01125
01126 while ((entry=readdir(parentDir))) {
01127 Key *keyEntry;
01128 char *transformedName=0;
01129 size_t keyNameSize=0;
01130
01131
01132 if (!strcmp(entry->d_name,".") || !strcmp(entry->d_name,"..")) continue;
01133
01134
01135 if ((*entry->d_name == '.') && !(options & KDB_O_INACTIVE)) continue;
01136
01137
01138 if (!transformedName) {
01139 transformedName=
01140 realloc(transformedName,keyNameSize=strblen(entry->d_name));
01141 strcpy(transformedName,entry->d_name);
01142 }
01143 if (UTF8Engine(UTF8_FROM,&transformedName,&keyNameSize)) {
01144 free(transformedName);
01145 return -1;
01146 }
01147
01148
01149 sprintf(buffer,"%s/%s",realParentName,transformedName);
01150 free(transformedName);
01151
01152 keyEntry=(Key *)malloc(sizeof(Key)); keyInit(keyEntry);
01153 keySetName(keyEntry,buffer);
01154
01155 if (options & KDB_O_STATONLY) kdbStatKey(keyEntry);
01156 else if (options & KDB_O_NFOLLOWLINK) {
01157 kdbStatKey(keyEntry);
01158 if (!keyIsLink(keyEntry)) kdbGetKey(keyEntry);
01159 } else {
01160 int rc=kdbGetKey(keyEntry);
01161
01162 if (rc && errno==KDB_RET_NOCRED) kdbStatKey(keyEntry);
01163 }
01164
01165 if (S_ISDIR(keyEntry->access)) {
01166 if (options & KDB_O_RECURSIVE) {
01167 KeySet children;
01168 char *fullName;
01169 size_t fullNameSize;
01170
01171 fullName=malloc(fullNameSize=keyGetFullNameSize(keyEntry));
01172 keyGetFullName(keyEntry,fullName,fullNameSize);
01173
01174 ksInit(&children);
01175
01176 kdbGetChildKeys(fullName,&children, ~(KDB_O_SORT) & options);
01177
01178
01179 if (options & KDB_O_DIR) ksAppend(returned,keyEntry);
01180 else {
01181 keyClose(keyEntry);
01182 free(keyEntry);
01183 }
01184
01185
01186 ksAppendKeys(returned,&children);
01187 free(fullName);
01188 } else if (options & KDB_O_DIR) ksAppend(returned,keyEntry);
01189 else {
01190 keyClose(keyEntry);
01191 free(keyEntry);
01192 }
01193 } else if (options & KDB_O_NOVALUE) {
01194 keyClose(keyEntry);
01195 free(keyEntry);
01196 } else ksAppend(returned,keyEntry);
01197 }
01198 keyClose(&parentKey);
01199 free(realParentName);
01200
01201 if ((options & (KDB_O_SORT)) && (returned->size > 1)) {
01202 Key *keys[returned->size];
01203 Key *cursor;
01204 size_t c=0;
01205
01206 for (cursor=returned->start; cursor; cursor=cursor->next, c++)
01207 keys[c]=cursor;
01208
01209 qsort(keys,returned->size,sizeof(Key *),keyCompareByName);
01210
01211 returned->start=cursor=keys[0];
01212 for (c=1; c<returned->size; c++) {
01213 cursor->next=keys[c];
01214 cursor=cursor->next;
01215 }
01216 cursor->next=0;
01217 returned->end=cursor;
01218 }
01219
01220 return 0;
01221 }
01222
01223
01224
01225
01226
01227
01228
01229
01240 int kdbGetRootKeys(KeySet *returned) {
01241 Key *system=0,*user=0;
01242
01243 system=malloc(sizeof(Key));
01244 keyInit(system);
01245 keySetName(system,"system");
01246 if (kdbGetKey(system)) {
01247 free(system);
01248 system=0;
01249 }
01250
01251 user=malloc(sizeof(Key));
01252 keyInit(user);
01253 keySetName(user,"user");
01254 if (kdbGetKey(user)) {
01255 free(user);
01256 user=0;
01257 }
01258
01259 if (system) ksInsert(returned,system);
01260 if (user) ksAppend(returned,user);
01261
01262 return 0;
01263 }
01264
01265
01266
01278 int kdbStatKey(Key *key) {
01279 char keyFileName[MAX_PATH_LENGTH];
01280 struct stat keyFileNameInfo;
01281 size_t pos;
01282 u_int32_t semiflag;
01283
01284 pos=kdbGetFilename(key,keyFileName,sizeof(keyFileName));
01285 if (!pos) return -1;
01286
01287 if (lstat(keyFileName,&keyFileNameInfo)) return -1;
01288 keyFromStat(key,&keyFileNameInfo);
01289
01290 if (keyIsLink(key) && key->recordSize) {
01291 char *data=malloc(key->recordSize+1);
01292
01293 readlink(keyFileName,data,key->recordSize);
01294 data[key->recordSize]=0;
01295 keySetLink(key,data);
01296 free(data);
01297 }
01298
01299
01300 semiflag=KEY_FLAG_NEEDSYNC;
01301 semiflag=~semiflag;
01302 key->flags &= semiflag;
01303 key->flags |= KEY_FLAG_ACTIVE;
01304
01305 return 0;
01306 }
01307
01308
01309
01318 int kdbGetKey(Key *key) {
01319 char keyFileName[500];
01320 struct stat keyFileNameInfo;
01321 int fd;
01322 size_t pos;
01323 u_int32_t semiflag;
01324
01325 pos=kdbGetFilename(key,keyFileName,sizeof(keyFileName));
01326 if (!pos) return -1;
01327
01328 if ((fd=open(keyFileName,O_RDONLY))==-1) return -1;
01329
01330 fstat(fd,&keyFileNameInfo);
01331 keyFromStat(key,&keyFileNameInfo);
01332 if (!keyIsDir(key)) {
01333 FILE *input;
01334
01335 input=fdopen(fd,"r");
01336 if (keyFileUnserialize(key,input)) {
01337 fclose(input);
01338 return -1;
01339 }
01340
01341 fclose(input);
01342 } else close(fd);
01343
01344
01345 semiflag=KEY_FLAG_NEEDSYNC;
01346 semiflag=~semiflag;
01347 key->flags &= semiflag;
01348
01349 return 0;
01350 }
01351
01352
01353
01376 int kdbSetKeys(KeySet *ks) {
01377 Key *current=ksCurrent(ks);
01378 int ret;
01379
01380 if (!current) current=ksNext(ks);
01381 while (current) {
01382 if (keyNeedsSync(current))
01383 if ((ret=kdbSetKey(current)))
01384 return ret;
01385
01386 current=ksNext(ks);
01387 }
01388
01389 return 0;
01390 }
01391
01392
01393
01404 int kdbSetKey(Key *key) {
01405 char keyFileName[MAX_PATH_LENGTH];
01406 char folderMaker[MAX_PATH_LENGTH];
01407 char *cursor, *last;
01408 int fd;
01409 FILE *output=0;
01410 size_t pos;
01411 u_int32_t semiflag;
01412 struct stat stated;
01413
01414 pos=kdbGetFilename(key,keyFileName,sizeof(keyFileName));
01415 if (!pos) return -1;
01416
01417 if (stat(keyFileName,&stated))
01418 if (errno==ENOENT) {
01419
01420 last=rindex(keyFileName,'/');
01421 strncpy(folderMaker,keyFileName,last-keyFileName);
01422 folderMaker[last-keyFileName]=0;
01423 if (stat(folderMaker,&stated)) {
01424
01425 last =rindex(keyFileName,'/');
01426 cursor = index(keyFileName,'/'); cursor++;
01427 if (!last || !cursor) {
01428 errno=KDB_RET_INVALIDKEY;
01429 return -1;
01430 }
01431 for (cursor=index(cursor,'/');
01432 cursor && (cursor <= last);
01433 cursor=index(cursor,'/')) {
01434 strncpy(folderMaker,keyFileName,cursor-keyFileName);
01435 folderMaker[cursor-keyFileName]=0;
01436 if (mkdir(folderMaker,0775)<0 && errno!=EEXIST) return -1;
01437 cursor++;
01438 }
01439 }
01440 } else return -1;
01441 else {
01442
01443 if ( S_ISDIR(stated.st_mode) && !keyIsDir(key)) {
01444 errno=EISDIR;
01445 return -1;
01446 }
01447 if (!S_ISDIR(stated.st_mode) && keyIsDir(key)) {
01448 errno=ENOTDIR;
01449 return -1;
01450 }
01451 }
01452
01453
01454
01455 if (keyIsLink(key)) {
01456 char *targetName=0;
01457 Key target;
01458 int rc;
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468 keyInit(&target);
01469 if (key->data) targetName=malloc(key->dataSize);
01470 keyGetLink(key,targetName,key->dataSize);
01471
01472
01473 if (keySetName(&target,targetName)) {
01474
01475 targetName=realloc(targetName,MAX_PATH_LENGTH);
01476 kdbGetFilename(&target,targetName,MAX_PATH_LENGTH);
01477 keyClose(&target);
01478 } else if (errno==KDB_RET_INVALIDKEY) {
01479
01480 keyClose(&target);
01481 } else {
01482 keyClose(&target);
01483 return -1;
01484 }
01485
01486
01487
01488
01489
01490 rc=symlink(targetName,keyFileName);
01491 free(targetName);
01492
01493 return rc;
01494 } else if (keyIsDir(key)) {
01495 if (mkdir(keyFileName,keyGetAccess(key))<0 &&
01496 errno!=EEXIST) return -1;
01497 } else {
01498
01499
01500 fd=open(keyFileName,O_CREAT | O_RDWR | O_TRUNC, keyGetAccess(key));
01501
01502 if (fd==-1) return -1;
01503 if (getuid() == 0) fchown(fd,keyGetUID(key),keyGetGID(key));
01504 if (!(output=fdopen(fd,"w+"))) return -1;
01505 if (keyFileSerialize(key,output)) {
01506 fclose(output);
01507 return -1;
01508 }
01509
01510 fclose(output);
01511 }
01512
01513
01514 semiflag=KEY_FLAG_NEEDSYNC;
01515 semiflag=~semiflag;
01516 key->flags &= semiflag;
01517
01518 return 0;
01519 }
01520
01521
01522
01523
01532 int kdbRename(Key *key, const char *newName) {
01533 char oldFileName[MAX_PATH_LENGTH];
01534 char newFileName[MAX_PATH_LENGTH];
01535 Key newKey;
01536 int rc;
01537
01538 keyInit(&newKey);
01539 rc=keySetName(&newKey,newName);
01540 if (rc) return rc;
01541 rc=kdbGetFilename(key,oldFileName,sizeof(oldFileName));
01542 if (!rc) return -1;
01543 rc=kdbGetFilename(&newKey,newFileName,sizeof(newFileName));
01544 if (!rc) return -1;
01545
01546 return rename(oldFileName,newFileName);
01547 }
01548
01549
01550
01551
01552
01562 int kdbRemove(const char *keyName) {
01563 Key key;
01564 char fileName[MAX_PATH_LENGTH];
01565 off_t rc;
01566
01567 keyInit(&key);
01568 rc=keySetName(&key,keyName);
01569 if (rc==-1) return -1;
01570 rc=kdbGetFilename(&key,fileName,sizeof(fileName));
01571 keyClose(&key);
01572 if (!rc) return -1;
01573
01574 return remove(fileName);
01575 }
01576
01577
01578
01579
01580
01592 int kdbLink(const char *oldPath, const char *newKeyName) {
01593 Key key;
01594 int rc;
01595
01596 keyInit(&key);
01597 keySetName(&key,newKeyName);
01598 keySetLink(&key,oldPath);
01599
01600 rc=kdbSetKey(&key);
01601 keyClose(&key);
01602
01603 return rc;
01604 }
01605
01606
01607
01608
01669 u_int32_t kdbMonitorKeys(KeySet *interests, u_int32_t diffMask,
01670 unsigned long iterations, unsigned sleep) {
01671 Key *start,*current;
01672 u_int32_t diff;
01673 int infinitum=0;
01674
01675 if (!interests || !interests->size) return 0;
01676
01677
01678 if (!sleep) sleep=1000;
01679
01680 if (!iterations) infinitum=1;
01681 else infinitum=0;
01682
01683 current=start=ksCurrent(interests);
01684
01685 while (infinitum || --iterations) {
01686 do {
01687 diff=kdbMonitorKey(current,diffMask,1,0);
01688 if (diff) return diff;
01689 current=ksNext(interests);
01690 } while (current!=start);
01691
01692
01693 if (infinitum || iterations) usleep(sleep);
01694 }
01695 return 0;
01696 }
01697
01698
01699
01739 u_int32_t kdbMonitorKey(Key *interest, u_int32_t diffMask,
01740 unsigned long iterations, unsigned sleep) {
01741 Key tested;
01742 int rc;
01743 u_int32_t diff;
01744 int infinitum=0;
01745
01746
01747 if (!interest || !keyGetNameSize(interest)) return 0;
01748
01749
01750 if (!sleep) sleep=1000;
01751
01752 if (!iterations) infinitum=1;
01753 else infinitum=0;
01754
01755
01756 keyInit(&tested);
01757 keyDup(interest,&tested);
01758
01759 while (infinitum || --iterations) {
01760 rc=kdbGetKey(&tested);
01761 if (rc) {
01762
01763 switch (errno) {
01764 case KDB_RET_NOCRED:
01765 return KEY_FLAG_NEEDSYNC;
01766 case KDB_RET_NOTFOUND:
01767 return KEY_FLAG_FLAG;
01768 }
01769 }
01770 diff=keyCompare(&tested,interest);
01771 if (diff & diffMask) {
01772
01773 keyDup(&tested,interest);
01774 keyClose(&tested);
01775 return diff;
01776 }
01777
01778 if (infinitum || iterations) usleep(sleep);
01779 }
01780
01781 return 0;
01782 }
01783
01784
01785