Main Page | Modules | File List

key.c

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

Generated on Thu Aug 4 03:37:08 2005 for Elektra Project by doxygen 1.3.5