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
00059
00060 #define UTF8_TO 1
00061 #define UTF8_FROM 0
00062
00063 extern int errno;
00064
00065
00066
00067
00079
00080
00081
00082
00083
00084
00085
00086
00095 int kdbOpen() {
00096 return 0;
00097 }
00098
00106 int kdbClose() {
00107 return 0;
00108 }
00109
00120 size_t keyGetSerializedSize(const Key *key) {
00121 size_t size,tmp;
00122
00123
00124 size=5+sizeof(u_int8_t)+1;
00125 if (key->comment) size+=strblen(key->comment);
00126 size++;
00127 tmp=keyGetDataSize(key);
00128 size+=tmp;
00129 return size;
00130 }
00131
00145 size_t unencode(char *encoded,void *returned) {
00146 char byteInHexa[5]="0x";
00147 char *readCursor=encoded;
00148 char *writeCursor=returned;
00149
00150 if (!encoded) {
00151 if (returned) *(char *)returned=0;
00152 return 0;
00153 }
00154
00155 byteInHexa[4]=0;
00156 while (*readCursor) {
00157 if (isspace((int)*readCursor)) readCursor++;
00158 if (isxdigit((int)*readCursor)) {
00159 long int converted;
00160 byteInHexa[2]=readCursor[0];
00161 byteInHexa[3]=readCursor[1];
00162 converted=strtol(byteInHexa,0,16);
00163 *writeCursor=(unsigned char)converted;
00164
00165 readCursor+=2;
00166 writeCursor++;
00167 } else {
00168
00169 errno=KDB_RET_TYPEMISMATCH;
00170 return 0;
00171 }
00172 }
00173 return (long int)writeCursor-(long int)returned;
00174 }
00175
00182 int kdbNeedsUTF8Conversion() {
00183 setlocale(LC_ALL,0);
00184 return strcmp(nl_langinfo(CODESET),"UTF-8");
00185 }
00186
00187
00196 int UTF8Engine(int direction, char **string, size_t *inputByteSize) {
00197 char *currentCharset=0;
00198 char *converted=0;
00199 char *readCursor, *writeCursor;
00200 size_t bufferSize;
00201 iconv_t converter;
00202
00203 if (kdbNeedsUTF8Conversion()) currentCharset=nl_langinfo(CODESET);
00204 else return 0;
00205
00206 if (direction) converter=iconv_open("UTF-8",currentCharset);
00207 else converter=iconv_open(currentCharset,"UTF-8");
00208
00209 if (converter == (iconv_t)(-1)) return -1;
00210
00211 bufferSize=*inputByteSize*2;
00212 converted=malloc(bufferSize);
00213 if (!converted) return -1;
00214
00215 readCursor=*string;
00216 writeCursor=converted;
00217 if (iconv(converter,
00218 &readCursor,inputByteSize,
00219 &writeCursor,&bufferSize) == (size_t)(-1)) {
00220 free(converted);
00221 iconv_close(converter);
00222 return -1;
00223 }
00224
00225
00226 *inputByteSize=writeCursor-converted;
00227
00228 readCursor=*string;
00229
00230 *string=malloc(*inputByteSize);
00231
00232 memcpy(*string,converted,*inputByteSize);
00233
00234 free(readCursor);
00235
00236 free(converted);
00237
00238 iconv_close(converter);
00239
00240 return 0;
00241 }
00242
00243
00244
00245
00252 int handleOldKeyFileVersion(Key *key,FILE *input,u_int16_t nversion) {
00253 char generalBuffer[100];
00254 size_t currentBufferSize;
00255
00256 char type[5];
00257 char *data=0;
00258 size_t dataSize=0;
00259 char *comment=0;
00260 size_t commentSize=0;
00261
00262 int readComment=1;
00263 int eof=0;
00264
00265
00266
00267
00268
00269
00270
00271
00272 switch (nversion) {
00273 case 1: {
00274 if (!fgets(type, sizeof(type), input)) return -1;
00275
00276 while (readComment) {
00277 if (fgets(generalBuffer,sizeof(generalBuffer),input)) {
00278 if (memcmp(generalBuffer,"<DATA>\n\0",8)) {
00279
00280 currentBufferSize=strblen(generalBuffer);
00281 if (!comment) {
00282 comment=(char *)malloc(commentSize=currentBufferSize);
00283 strcpy(comment,generalBuffer);
00284 } else {
00285 char *buffer=0;
00286
00287 buffer=malloc(commentSize+currentBufferSize);
00288 strcpy(buffer,comment);
00289 strcat(buffer,generalBuffer);
00290 comment=realloc(comment,commentSize+=currentBufferSize);
00291 strcpy(comment,buffer);
00292 free(buffer);
00293 }
00294 } else readComment=0;
00295 } else {
00296 readComment=0;
00297 eof=1;
00298 }
00299 }
00300
00301
00302 if (commentSize > 1 && (*(comment+commentSize-2) == '\n')) {
00303 *(comment+commentSize-2)=0;
00304 --commentSize;
00305 }
00306
00307
00308 if (comment && UTF8Engine(UTF8_FROM,&comment,&commentSize)) {
00309 free(comment);
00310 return -1;
00311 }
00312
00313
00314 if (!eof) {
00315 while (fgets(generalBuffer,sizeof(generalBuffer),input)) {
00316 currentBufferSize=strlen(generalBuffer);
00317 if (!data) {
00318 data=(char *)malloc(dataSize=(currentBufferSize+1));
00319 strcpy(data,generalBuffer);
00320 } else {
00321 char *buffer=0;
00322
00323 buffer=malloc(dataSize+currentBufferSize);
00324 strcpy(buffer,data);
00325 strcat(buffer,generalBuffer);
00326 data=realloc(data,dataSize+=currentBufferSize);
00327 strcpy(data,buffer);
00328 free(buffer);
00329 }
00330 }
00331 }
00332
00333
00334 keySetComment(key,comment);
00335 if (comment) free(comment);
00336
00337
00338
00339 {
00340 u_int8_t oldVersion=atoi(type);
00341 switch (oldVersion) {
00342 case 1: keySetType(key,KEY_TYPE_BINARY); break;
00343 case 2: keySetType(key,KEY_TYPE_STRING); break;
00344 default: keySetType(key,oldVersion);
00345 }
00346 }
00347 if (!dataSize) {
00348 keySetRaw(key,0,0);
00349 return 0;
00350 }
00351
00352 if (keyGetType(key) <= KEY_TYPE_BINARY) {
00353
00354 char *unencoded=0;
00355 size_t unencodedSize;
00356
00357
00358 unencodedSize=dataSize/2;
00359
00360 unencoded=malloc(unencodedSize);
00361 if (!(unencodedSize=unencode(data,unencoded))) return -1;
00362 keySetRaw(key,unencoded,unencodedSize);
00363 free(unencoded);
00364 } else {
00365 if (UTF8Engine(UTF8_FROM,&data,&dataSize)) {
00366 free(data);
00367 return -1;
00368 }
00369 keySetRaw(key,data,dataSize);
00370 }
00371
00372 free(data);
00373
00374 return 0;
00375 }
00376 }
00377 return -1;
00378 }
00379
00380
00381
00382
00383
00392 int keyFileUnserialize(Key *key,FILE *input) {
00393 char generalBuffer[100];
00394 size_t currentBufferSize;
00395
00396 char version[10];
00397 u_int16_t nversion=0;
00398 char type[5];
00399 char *data=0;
00400 size_t dataSize=0;
00401 char *comment=0;
00402 size_t commentSize=0;
00403
00404 int readComment=1;
00405 int eof=0;
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 if (!fgets(version, sizeof(version), input)) return -1;
00418 if (strncmp(version,"RG",2)) {
00419
00420 errno=KDB_RET_INVALIDKEY;
00421 return -1;
00422 }
00423
00424 nversion=atoi(version+2);
00425 if (!nversion || nversion > RG_KEY_FORMAT_VERSION) {
00426 errno=KDB_RET_INVALIDKEY;
00427 return -1;
00428 }
00429
00430 if (nversion != RG_KEY_FORMAT_VERSION)
00431 return handleOldKeyFileVersion(key,input,nversion);
00432
00433 if (!fgets(type, sizeof(type), input)) return -1;
00434
00435 while (readComment) {
00436 if (fgets(generalBuffer,sizeof(generalBuffer),input)) {
00437 if (memcmp(generalBuffer,"<DATA>\n\0",8)) {
00438
00439 currentBufferSize=strblen(generalBuffer);
00440 if (!comment) {
00441 comment=(char *)malloc(commentSize=currentBufferSize);
00442 strcpy(comment,generalBuffer);
00443 } else {
00444 char *buffer=0;
00445
00446 buffer=malloc(commentSize+currentBufferSize);
00447 strcpy(buffer,comment);
00448 strcat(buffer,generalBuffer);
00449 comment=realloc(comment,commentSize+=currentBufferSize);
00450 strcpy(comment,buffer);
00451 free(buffer);
00452 }
00453 } else readComment=0;
00454 } else {
00455 readComment=0;
00456 eof=1;
00457 }
00458 }
00459
00460
00461 if (commentSize > 1 && (*(comment+commentSize-2) == '\n')) {
00462 *(comment+commentSize-2)=0;
00463 --commentSize;
00464 }
00465
00466 if (comment && UTF8Engine(UTF8_FROM,&comment,&commentSize)) {
00467 free(comment);
00468 return -1;
00469 }
00470
00471
00472 if (!eof) {
00473 while (fgets(generalBuffer,sizeof(generalBuffer),input)) {
00474 currentBufferSize=strlen(generalBuffer);
00475 if (!data) {
00476 data=(char *)malloc(dataSize=(currentBufferSize+1));
00477 strcpy(data,generalBuffer);
00478 } else {
00479 char *buffer=0;
00480
00481 buffer=malloc(dataSize+currentBufferSize);
00482 strcpy(buffer,data);
00483 strcat(buffer,generalBuffer);
00484 data=realloc(data,dataSize+=currentBufferSize);
00485 strcpy(data,buffer);
00486 free(buffer);
00487 }
00488 }
00489 }
00490
00491
00492 keySetComment(key,comment);
00493 if (comment) free(comment);
00494 keySetType(key,atoi(type));
00495 if (!dataSize) {
00496 keySetRaw(key,0,0);
00497 return 0;
00498 }
00499
00500 if (keyGetType(key) <= KEY_TYPE_BINARY) {
00501
00502 char *unencoded=0;
00503 size_t unencodedSize;
00504
00505
00506 unencodedSize=dataSize/2;
00507
00508 unencoded=malloc(unencodedSize);
00509 if (!(unencodedSize=unencode(data,unencoded))) return -1;
00510 keySetRaw(key,unencoded,unencodedSize);
00511 free(unencoded);
00512 } else {
00513 if (UTF8Engine(UTF8_FROM,&data,&dataSize)) {
00514 free(data);
00515 return -1;
00516 }
00517 keySetRaw(key,data,dataSize);
00518 }
00519
00520 free(data);
00521
00522 return 0;
00523 }
00524
00525
00526
00541 size_t encode(void *unencoded, size_t size, char *returned) {
00542 void *readCursor=unencoded;
00543 void *writeCursor=returned;
00544 int blockStep=4;
00545 int lineStep=8*blockStep;
00546 int currentInBlock=0;
00547 int currentInLine=0;
00548
00549 while ((readCursor-unencoded)<size) {
00550 sprintf(writeCursor,"%01x",*(u_int8_t *)readCursor);
00551 readCursor++;
00552 writeCursor+=2;
00553 currentInBlock++;
00554 currentInLine++;
00555 if (currentInLine==lineStep) {
00556 *(char *)writeCursor='\n'; writeCursor++;
00557 currentInLine=0;
00558 currentInBlock=0;
00559 }
00560 if (currentInBlock==blockStep) {
00561 *(char *)writeCursor=' '; writeCursor++;
00562 currentInBlock=0;
00563 }
00564 }
00565 *(char *)writeCursor='\n';
00566 *(char *)++writeCursor=0;
00567 return (writeCursor)-(void *)returned;
00568 }
00569
00570
00571
00572
00573
00584 int keyFileSerialize(Key *key, FILE *output) {
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 size_t dataSize;
00596
00597 fprintf(output,"RG%03d\n",RG_KEY_FORMAT_VERSION);
00598 fprintf(output,"%d\n",key->type);
00599 if (key->comment) {
00600 if (kdbNeedsUTF8Conversion()) {
00601 size_t convertedCommentSize=key->commentSize;
00602 char *convertedComment=malloc(convertedCommentSize);
00603
00604 memcpy(convertedComment,key->comment,key->commentSize);
00605 if (UTF8Engine(UTF8_TO,&convertedComment,&convertedCommentSize)) {
00606 free(convertedComment);
00607 return -1;
00608 }
00609 fprintf(output,"%s\n",convertedComment);
00610 free(convertedComment);
00611 } else fprintf(output,"%s\n",key->comment);
00612 }
00613
00614 fputs("<DATA>\n",output);
00615 fflush(output);
00616
00617 dataSize=keyGetDataSize(key);
00618 if (dataSize) {
00619
00620 if (keyGetType(key) > KEY_TYPE_BINARY) {
00621 if (kdbNeedsUTF8Conversion()) {
00622 size_t convertedDataSize=key->dataSize;
00623 char *convertedData=malloc(convertedDataSize);
00624
00625 memcpy(convertedData,key->data,key->dataSize);
00626 if (UTF8Engine(UTF8_TO,&convertedData,&convertedDataSize)) {
00627 free(convertedData);
00628 return -1;
00629 }
00630 fprintf(output,"%s",convertedData);
00631 free(convertedData);
00632 } else fputs(key->data,output);
00633 } else {
00634 char *encoded=malloc(3*dataSize);
00635 size_t encodedSize;
00636
00637 encodedSize=encode(key->data,dataSize,encoded);
00638 fwrite(encoded,encodedSize,1,output);
00639 free(encoded);
00640 }
00641 }
00642 return 0;
00643 }
00644
00645
00655 size_t keyCalcRelativeFileName(Key *key,char *relativeFileName,size_t maxSize) {
00656 if (!key || !keyIsInitialized(key)) {
00657 errno=KDB_RET_UNINITIALIZED;
00658 return 0;
00659 }
00660 if (!key->key) {
00661 errno=KDB_RET_NOKEY;
00662 return 0;
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 if (kdbNeedsUTF8Conversion()) {
00689 char *converted;
00690 size_t size;
00691
00692 if (!(size=keyGetNameSize(key))) return 0;
00693
00694 converted=malloc(size);
00695 keyGetName(key,converted,size);
00696
00697
00698
00699 if (UTF8Engine(UTF8_TO,&converted,&size)) {
00700 free(converted);
00701 return 0;
00702 }
00703
00704 if (size>maxSize) {
00705 free(converted);
00706 errno=E2BIG;
00707 return 0;
00708 }
00709
00710 memcpy(relativeFileName,converted,size);
00711 free(converted);
00712
00713 return size;
00714 } else return keyGetName(key,relativeFileName,maxSize);
00715
00716 return 0;
00717 }
00718
00719
00720
00721
00722
00723
00735 int keyFromStat(Key *key,struct stat *stat) {
00736 if (!key) {
00737 errno=KDB_RET_NULLKEY;
00738 return -1;
00739 }
00740
00741 keySetAccess(key,stat->st_mode);
00742 keySetUID(key,stat->st_uid);
00743 keySetGID(key,stat->st_gid);
00744 if (S_ISDIR(stat->st_mode)) keySetType(key,KEY_TYPE_DIR);
00745 key->atime=stat->st_atime;
00746 key->mtime=stat->st_mtime;
00747 key->ctime=stat->st_ctime;
00748 key->recordSize=stat->st_size;
00749 return 0;
00750 }
00751
00752
00753
00754
00764 size_t kdbGetFilename(Key *forKey,char *returned,size_t maxSize) {
00765 size_t length=0;
00766
00767 switch (keyGetNamespace(forKey)) {
00768 case KEY_NS_SYSTEM: {
00769
00770 strncpy(returned,RG_DB_SYSTEM,maxSize);
00771 length=strlen(returned);
00772 break;
00773 }
00774 case KEY_NS_USER: {
00775
00776 struct passwd *user=0;
00777 char userName[100];
00778
00779 length=keyGetOwner(forKey,userName,sizeof(userName));
00780 if (!length) strncpy(userName,getenv("USER"),sizeof(userName));
00781
00782 user=getpwnam(userName);
00783 if (!user) return 0;
00784 length=snprintf(returned,maxSize,"%s/%s",user->pw_dir,RG_DB_USER);
00785 break;
00786 }
00787 default: {
00788 errno=KDB_RET_INVALIDKEY;
00789 return 0;
00790 }
00791 }
00792
00793 returned[length]='/'; length++;
00794 length+=keyCalcRelativeFileName(forKey,returned+length,maxSize-length);
00795
00796 return length;
00797 }
00798
00799
00800
00817 int kdbGetValue(const char *keyname, char *returned,size_t maxSize) {
00818 Key key;
00819 int rc=0;
00820
00821 keyInit(&key);
00822 keySetName(&key,keyname);
00823 rc=kdbGetKey(&key);
00824 if (rc == 0) keyGetString(&key,returned,maxSize);
00825 else rc=errno;
00826 keyClose(&key);
00827 errno=rc;
00828 return rc;
00829 }
00830
00831
00832
00848 int kdbSetValue(const char *keyname, const char *value) {
00849 Key key;
00850 int rc;
00851
00852
00853 keySetName(&key,keyname);
00854 rc=kdbGetKey(&key);
00855 keySetString(&key,value);
00856 rc=kdbSetKey(&key);
00857 keyClose(&key);
00858 return rc;
00859 }
00860
00861
00862
00889 int kdbGetValueByParent(const char *parentName, const char *baseName, char *returned, size_t maxSize) {
00890 char name[strblen(parentName)+strblen(baseName)];
00891
00892 sprintf(name,"%s/%s",parentName,baseName);
00893 return kdbGetValue(name,returned,maxSize);
00894 }
00895
00896
00897
00907 int kdbSetValueByParent(const char *parentName, const char *baseName, const char *value) {
00908 char name[strblen(parentName)+strblen(baseName)];
00909
00910 sprintf(name,"%s/%s",parentName,baseName);
00911 return kdbSetValue(name,value);
00912 }
00913
00914
00915
00932 int kdbGetKeyByParent(const char *parentName, const char *baseName, Key *returned) {
00933 char name[strblen(parentName)+strblen(baseName)];
00934
00935 sprintf(name,"%s/%s",parentName,baseName);
00936 keySetName(returned,name);
00937
00938 return kdbGetKey(returned);
00939 }
00940
00941
00951 int kdbGetKeyByParentKey(const Key *parent, const char *baseName, Key *returned) {
00952 size_t size=keyGetFullNameSize(parent);
00953 char name[size+strblen(baseName)];
00954
00955 keyGetFullName(parent,name,size);
00956 name[size-1]='/';
00957 strcpy((char *)(parent+size),baseName);
00958
00959 keySetName(returned,name);
00960
00961 return kdbGetKey(returned);
00962 }
00963
00964
00965
00966
00967
00968 int keyCompareByName(const void *p1, const void *p2) {
00969 Key *key1=*(Key **)p1;
00970 Key *key2=*(Key **)p2;
00971
00972 return strcmp(key1->key, key2->key);
00973 }
00974
00975
00976
01040 int kdbGetChildKeys(const char *parentName, KeySet *returned, unsigned long options) {
01041 char *realParentName=0;
01042 size_t parentNameSize;
01043 DIR *parentDir;
01044 Key parentKey;
01045 char buffer[800];
01046 struct dirent *entry;
01047
01048
01049
01050
01051
01052
01053 keyInit(&parentKey);
01054 keySetName(&parentKey,parentName);
01055 kdbGetFilename(&parentKey,buffer,sizeof(buffer));
01056 parentDir=opendir(buffer);
01057
01058
01059
01060 if (!parentDir) return -1;
01061
01062 parentNameSize=keyGetFullNameSize(&parentKey);
01063 realParentName=realloc(realParentName,parentNameSize);
01064 keyGetFullName(&parentKey,realParentName,parentNameSize);
01065
01066 while ((entry=readdir(parentDir))) {
01067 Key *keyEntry;
01068 char *transformedName=0;
01069 size_t keyNameSize=0;
01070
01071
01072 if (!strcmp(entry->d_name,".") || !strcmp(entry->d_name,"..")) continue;
01073
01074
01075 if ((*entry->d_name == '.') && !(options & KDB_O_INACTIVE)) continue;
01076
01077
01078 if (!transformedName) {
01079 transformedName=
01080 realloc(transformedName,keyNameSize=strblen(entry->d_name));
01081 strcpy(transformedName,entry->d_name);
01082 }
01083 if (UTF8Engine(UTF8_FROM,&transformedName,&keyNameSize)) {
01084 free(transformedName);
01085 return -1;
01086 }
01087
01088
01089 sprintf(buffer,"%s/%s",realParentName,transformedName);
01090 free(transformedName);
01091
01092 keyEntry=(Key *)malloc(sizeof(Key)); keyInit(keyEntry);
01093 keySetName(keyEntry,buffer);
01094
01095 if (options & KDB_O_STATONLY) kdbStatKey(keyEntry);
01096 else if (options & KDB_O_NFOLLOWLINK) {
01097 kdbStatKey(keyEntry);
01098 if (!keyIsLink(keyEntry)) kdbGetKey(keyEntry);
01099 } else {
01100 int rc=kdbGetKey(keyEntry);
01101
01102 if (rc && errno==KDB_RET_NOCRED) kdbStatKey(keyEntry);
01103 }
01104
01105 if (S_ISDIR(keyEntry->access)) {
01106 if (options & KDB_O_RECURSIVE) {
01107 KeySet children;
01108 char *fullName;
01109 size_t fullNameSize;
01110
01111 fullName=malloc(fullNameSize=keyGetFullNameSize(keyEntry));
01112 keyGetFullName(keyEntry,fullName,fullNameSize);
01113
01114 ksInit(&children);
01115
01116 kdbGetChildKeys(fullName,&children, ~(KDB_O_SORT) & options);
01117
01118
01119 if (options & KDB_O_DIR) ksAppend(returned,keyEntry);
01120 else {
01121 keyClose(keyEntry);
01122 free(keyEntry);
01123 }
01124
01125
01126 ksAppendKeys(returned,&children);
01127 free(fullName);
01128 } else if (options & KDB_O_DIR) ksAppend(returned,keyEntry);
01129 else {
01130 keyClose(keyEntry);
01131 free(keyEntry);
01132 }
01133 } else if (options & KDB_O_NOVALUE) {
01134 keyClose(keyEntry);
01135 free(keyEntry);
01136 } else ksAppend(returned,keyEntry);
01137 }
01138 keyClose(&parentKey);
01139 free(realParentName);
01140
01141 if ((options & (KDB_O_SORT)) && (returned->size > 1)) {
01142 Key *keys[returned->size];
01143 Key *cursor;
01144 size_t c=0;
01145
01146 for (cursor=returned->start; cursor; cursor=cursor->next, c++)
01147 keys[c]=cursor;
01148
01149 qsort(keys,returned->size,sizeof(Key *),keyCompareByName);
01150
01151 returned->start=cursor=keys[0];
01152 for (c=1; c<returned->size; c++) {
01153 cursor->next=keys[c];
01154 cursor=cursor->next;
01155 }
01156 cursor->next=0;
01157 returned->end=cursor;
01158 }
01159
01160 return 0;
01161 }
01162
01163
01164
01165
01166
01167
01168
01169
01180 int kdbGetRootKeys(KeySet *returned) {
01181 Key *system=0,*user=0;
01182
01183 system=malloc(sizeof(Key));
01184 keyInit(system);
01185 keySetName(system,"system");
01186 if (kdbGetKey(system)) {
01187 free(system);
01188 system=0;
01189 }
01190
01191 user=malloc(sizeof(Key));
01192 keyInit(user);
01193 keySetName(user,"user");
01194 if (kdbGetKey(user)) {
01195 free(user);
01196 user=0;
01197 }
01198
01199 if (system) ksInsert(returned,system);
01200 if (user) ksAppend(returned,user);
01201
01202 return 0;
01203 }
01204
01205
01206
01218 int kdbStatKey(Key *key) {
01219 char keyFileName[800];
01220 struct stat keyFileNameInfo;
01221 size_t pos;
01222 u_int32_t semiflag;
01223
01224 pos=kdbGetFilename(key,keyFileName,sizeof(keyFileName));
01225 if (!pos) return -1;
01226
01227 if (lstat(keyFileName,&keyFileNameInfo)) return -1;
01228 keyFromStat(key,&keyFileNameInfo);
01229
01230 if (keyIsLink(key) && key->recordSize) {
01231 char *data=malloc(key->recordSize+1);
01232
01233 readlink(keyFileName,data,key->recordSize);
01234 data[key->recordSize]=0;
01235 keySetLink(key,data);
01236 free(data);
01237 }
01238
01239
01240 semiflag=KEY_FLAG_NEEDSYNC;
01241 semiflag=~semiflag;
01242 key->flags &= semiflag;
01243 key->flags |= KEY_FLAG_ACTIVE;
01244
01245 return 0;
01246 }
01247
01248
01249
01258 int kdbGetKey(Key *key) {
01259 char keyFileName[500];
01260 struct stat keyFileNameInfo;
01261 int fd;
01262 size_t pos;
01263 u_int32_t semiflag;
01264
01265 pos=kdbGetFilename(key,keyFileName,sizeof(keyFileName));
01266 if (!pos) return -1;
01267
01268 if ((fd=open(keyFileName,O_RDONLY))==-1) return -1;
01269
01270 fstat(fd,&keyFileNameInfo);
01271 keyFromStat(key,&keyFileNameInfo);
01272 if (!keyIsDir(key)) {
01273 FILE *input;
01274
01275 input=fdopen(fd,"r");
01276 if (keyFileUnserialize(key,input)) {
01277 fclose(input);
01278 return -1;
01279 }
01280
01281 fclose(input);
01282 } else close(fd);
01283
01284
01285 semiflag=KEY_FLAG_NEEDSYNC;
01286 semiflag=~semiflag;
01287 key->flags &= semiflag;
01288
01289 return 0;
01290 }
01291
01292
01293
01306 int kdbSetKeys(KeySet *ks) {
01307 Key *current;
01308
01309 for (current=ks->start; current; current=current->next) {
01310 if (keyNeedsSync(current)) {
01311 kdbSetKey(current);
01312 }
01313 }
01314
01315 return 0;
01316 }
01317
01318
01319
01330 int kdbSetKey(Key *key) {
01331 char keyFileName[800];
01332 char folderMaker[800];
01333 char *cursor, *last;
01334 int fd;
01335 FILE *output=0;
01336 size_t pos;
01337 u_int32_t semiflag;
01338 struct stat stated;
01339
01340 pos=kdbGetFilename(key,keyFileName,sizeof(keyFileName));
01341 if (!pos) return -1;
01342
01343 if (stat(keyFileName,&stated))
01344 if (errno==ENOENT) {
01345
01346 last=rindex(keyFileName,'/');
01347 strncpy(folderMaker,keyFileName,last-keyFileName);
01348 folderMaker[last-keyFileName]=0;
01349 if (stat(folderMaker,&stated)) {
01350
01351 last =rindex(keyFileName,'/');
01352 cursor = index(keyFileName,'/'); cursor++;
01353 if (!last || !cursor) {
01354 errno=KDB_RET_INVALIDKEY;
01355 return -1;
01356 }
01357 for (cursor=index(cursor,'/');
01358 cursor && (cursor <= last);
01359 cursor=index(cursor,'/')) {
01360 strncpy(folderMaker,keyFileName,cursor-keyFileName);
01361 folderMaker[cursor-keyFileName]=0;
01362 if (mkdir(folderMaker,0775)<0 && errno!=EEXIST) return -1;
01363 cursor++;
01364 }
01365 }
01366 } else return -1;
01367 else {
01368
01369 if ( S_ISDIR(stated.st_mode) && !keyIsDir(key)) {
01370 errno=EISDIR;
01371 return -1;
01372 }
01373 if (!S_ISDIR(stated.st_mode) && keyIsDir(key)) {
01374 errno=ENOTDIR;
01375 return -1;
01376 }
01377 }
01378
01379
01380
01381 if (keyIsLink(key)) {
01382 char *targetName=0;
01383 Key target;
01384 int rc;
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394 keyInit(&target);
01395 if (key->data) targetName=malloc(key->dataSize);
01396 keyGetLink(key,targetName,key->dataSize);
01397
01398
01399 if (keySetName(&target,targetName)) {
01400
01401 targetName=realloc(targetName,800);
01402 kdbGetFilename(&target,targetName,800);
01403 keyClose(&target);
01404 } else if (errno==KDB_RET_INVALIDKEY) {
01405
01406 keyClose(&target);
01407 } else {
01408 keyClose(&target);
01409 return -1;
01410 }
01411
01412
01413
01414
01415
01416 rc=symlink(targetName,keyFileName);
01417 free(targetName);
01418
01419 return rc;
01420 } else if (keyIsDir(key)) {
01421 if (mkdir(keyFileName,keyGetAccess(key))<0 &&
01422 errno!=EEXIST) return -1;
01423 } else {
01424
01425
01426 fd=open(keyFileName,O_CREAT | O_RDWR | O_TRUNC, keyGetAccess(key));
01427
01428 if (fd==-1) return -1;
01429 if (getuid() == 0) fchown(fd,keyGetUID(key),keyGetGID(key));
01430 if (!(output=fdopen(fd,"w+"))) return -1;
01431 if (keyFileSerialize(key,output)) {
01432 fclose(output);
01433 return -1;
01434 }
01435
01436 fclose(output);
01437 }
01438
01439
01440 semiflag=KEY_FLAG_NEEDSYNC;
01441 semiflag=~semiflag;
01442 key->flags &= semiflag;
01443
01444 return 0;
01445 }
01446
01447
01448
01449
01450
01451
01461 int kdbRemove(const char *keyName) {
01462 Key key;
01463 char fileName[800];
01464 off_t rc;
01465
01466 keyInit(&key);
01467 rc=keySetName(&key,keyName);
01468 if (rc==-1) return -1;
01469 rc=kdbGetFilename(&key,fileName,sizeof(fileName));
01470 keyClose(&key);
01471 if (!rc) return -1;
01472
01473 return remove(fileName);
01474 }
01475
01476
01477
01478
01479
01491 int kdbLink(const char *oldPath, const char *newKeyName) {
01492 Key key;
01493 int rc;
01494
01495 keyInit(&key);
01496 keySetName(&key,newKeyName);
01497 keySetLink(&key,oldPath);
01498
01499 rc=kdbSetKey(&key);
01500 keyClose(&key);
01501
01502 return rc;
01503 }
01504
01505
01506
01507
01508
01569 u_int32_t kdbMonitorKeys(KeySet *interests, u_int32_t diffMask,
01570 unsigned long iterations, unsigned sleep) {
01571 Key *start,*current;
01572 u_int32_t diff;
01573 int infinitum=0;
01574
01575 if (!interests || !interests->size) return 0;
01576
01577
01578 if (!sleep) sleep=1000;
01579
01580 if (!iterations) infinitum=1;
01581 else infinitum=0;
01582
01583 current=start=ksCurrent(interests);
01584
01585 while (infinitum || --iterations) {
01586 do {
01587 diff=kdbMonitorKey(current,diffMask,1,0);
01588 if (diff) return diff;
01589 current=ksNext(interests);
01590 } while (current!=start);
01591
01592
01593 if (infinitum || iterations) usleep(sleep);
01594 }
01595 return 0;
01596 }
01597
01598
01599
01639 u_int32_t kdbMonitorKey(Key *interest, u_int32_t diffMask,
01640 unsigned long iterations, unsigned sleep) {
01641 Key tested;
01642 int rc;
01643 u_int32_t diff;
01644 int infinitum=0;
01645
01646
01647 if (!interest || !keyGetNameSize(interest)) return 0;
01648
01649
01650 if (!sleep) sleep=1000;
01651
01652 if (!iterations) infinitum=1;
01653 else infinitum=0;
01654
01655
01656 keyInit(&tested);
01657 keyDup(interest,&tested);
01658
01659 while (infinitum || --iterations) {
01660 rc=kdbGetKey(&tested);
01661 if (rc) {
01662
01663 switch (errno) {
01664 case KDB_RET_NOCRED:
01665 return KEY_FLAG_NEEDSYNC;
01666 case KDB_RET_NOTFOUND:
01667 return KEY_FLAG_FLAG;
01668 }
01669 }
01670 diff=keyCompare(&tested,interest);
01671 if (diff & diffMask) {
01672
01673 keyDup(&tested,interest);
01674 keyClose(&tested);
01675 return diff;
01676 }
01677
01678 if (infinitum || iterations) usleep(sleep);
01679 }
01680
01681 return 0;
01682 }
01683
01684
01685