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

Generated on Tue Aug 31 08:40:42 2004 for Elektra Project by doxygen 1.3.6