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 BSD License (revised).                      *
00013  *                                                                         *
00014  ***************************************************************************/
00015 
00016 /* Subversion stuff
00017 
00018 $Id: key.c 947 2006-12-29 08:49:48Z aviram $
00019 
00020 */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026 
00027 #include <stdio.h>
00028 #include <stdarg.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <errno.h>
00032 
00033 #ifdef HAVE_STRINGS_H
00034 #include <strings.h>
00035 #endif
00036 
00037 #ifdef HAVE_SYS_STAT_H
00038 #include <sys/stat.h>
00039 #endif
00040 
00041 #ifdef HAVE_UNISTD_H
00042 #include <unistd.h>
00043 #endif
00044 
00045 #ifdef WIN32
00046 #include <io.h>
00047 #endif
00048 
00049 #ifdef HAVE_SYS_TYPES_H
00050 #include <sys/types.h>
00051 #endif
00052 
00053 #ifdef HAVE_PWD_H
00054 #include <pwd.h>
00055 #endif
00056 
00057 #ifdef HAVE_GRP_H
00058 #include <grp.h>
00059 #endif
00060 
00061 #ifdef HAVE_LANGINFO_H
00062 #include <langinfo.h>
00063 #endif
00064 
00065 #include "kdb.h"
00066 #include "kdbprivate.h"
00067 
00077 size_t strblen(const char *s) {
00078     char *found=strchr(s,0);
00079     if (found) return found-s+1;
00080     return 0;
00081 }
00082 
00083 
00084 
00373 Key *keyNew(const char *keyName, ...) {
00374     va_list va;
00375     Key *key;
00376     uint32_t action=0;
00377     uint8_t keyType=KEY_TYPE_UNDEFINED;
00378     uint8_t keyTypeBinary=0; /* a boolean shortcut */
00379     size_t valueSize=0;
00380     
00381     key=(Key *)malloc(sizeof(Key));
00382     if (!key) return 0;
00383     keyInit(key);
00384     
00385     if (keyName) {
00386         size_t nameSize;
00387         
00388         nameSize=keySetName(key,keyName);
00389         if (! nameSize) {
00390             free(key);
00391             return 0;
00392         }
00393         
00394         va_start(va,keyName);
00395         
00396         action=va_arg(va,uint32_t);
00397         while (action) {
00398             switch (action) {
00399                 case KEY_SWITCH_TYPE:
00400                     /* We are waiting for 1 or 2 parameters
00401                      * following this action */
00402                     
00403                     /* First is the type */
00404                     keyType=(uint8_t)va_arg(va,unsigned int);
00405                     
00406                     if (keyType == KEY_TYPE_DIR) {
00407                         mode_t mask=umask(0);
00408                         
00409                         umask(mask);
00410                         keySetDir(key,mask);
00411                         keyType=KEY_TYPE_UNDEFINED;
00412                     } else {
00413                         keyTypeBinary=(KEY_TYPE_BINARY <= keyType &&
00414                             keyType < KEY_TYPE_STRING);
00415                     
00416                         keySetType(key,keyType);
00417                     }
00418                     break;
00419                 case KEY_SWITCH_VALUE:
00420                     if (keyType == KEY_TYPE_UNDEFINED)
00421                         keyType=KEY_TYPE_STRING;
00422 
00423                     if (!keyTypeBinary) {
00424                         /* most popular cases */
00425                         keySetString(key,va_arg(va,char *));
00426                         /* reset the type due to the
00427                          * above keySetString override */
00428                         keySetType(key,keyType);
00429                     } else {
00430                         /* Binary val: we need first the value then the size */
00431                         void *value=va_arg(va,void *);
00432                         valueSize=va_arg(va,size_t);
00433                         keySetRaw(key,value,valueSize);
00434                     }
00435 
00436                     break;
00437                 case KEY_SWITCH_UID:
00438                     keySetUID(key,va_arg(va,uid_t));
00439                     break;
00440                 case KEY_SWITCH_GID:
00441                     keySetGID(key,va_arg(va,gid_t));
00442                     break;
00443                 case KEY_SWITCH_MODE:
00444                     keySetAccess(key,va_arg(va,mode_t));
00445                     break;
00446                 case KEY_SWITCH_UMODE:
00447                     if (keyIsDir(key))
00448                         keySetDir(key,va_arg(va,mode_t));
00449                     else
00450                         keySetUAccess(key,va_arg(va,mode_t));
00451                     break;
00452                 case KEY_SWITCH_DOMAIN:
00453                     keySetOwner(key,va_arg(va,char *));
00454                     break;
00455                 case KEY_SWITCH_COMMENT:
00456                     keySetComment(key,va_arg(va,char *));
00457                     break;
00458                 case KEY_SWITCH_NEEDSYNC: {
00459                     int rc=0;
00460                     rc=kdbGetKey(va_arg(va,KDBHandle),key);
00461                     if (rc)
00462                         /* Flag the key to indicate an error in
00463                          * kdbGetKey(). Propagated errno will indicate
00464                          * the error ocurred. */
00465                         key->flags|=KEY_SWITCH_FLAG; /* same as keySetFlag(key) */
00466                 } break;
00467             }
00468             action=va_arg(va,uint32_t);
00469         }
00470         va_end(va);
00471     }
00472     return key;
00473 }
00474  
00475  
00476  
00477  
00490 int keyDel(Key *key) {
00491     int rc;
00492     
00493     rc=keyClose(key);
00494     free(key);
00495     
00496     return rc;
00497  }
00498 
00499  
00500 
00501 
00502 
00513 int keyIsInitialized(const Key *key) {
00514     /* if (!key) return 0; */ /* removing to activate stupid mode */
00515     return ((key->flags & KEY_SWITCH_INITMASK)==KEY_SWITCH_INITIALIZED);
00516 }
00517 
00518 
00519 /*******************************************
00520  *    General name manipulation methods    *
00521  *******************************************/
00522 
00523 
00569 char *keyNameGetOneLevel(const char *keyName, size_t *size) {
00570     char *real=(char *)keyName;
00571     size_t cursor=0;
00572     int escapeNext=0;
00573     int end=0;
00574     
00575     /* skip all repeating '/' in the begining */
00576     while (*real && *real == RG_KEY_DELIM) real++;
00577     
00578     /* now see where this basename ends handling escaped chars with '\' */
00579     while (real[cursor] && ! end) {
00580         switch (real[cursor]) {
00581             case '\\':
00582                 escapeNext=1;
00583                 break;
00584             case RG_KEY_DELIM:
00585                 if (! escapeNext) end=1;
00586             default:
00587                 escapeNext=0;
00588         }
00589         ++cursor;
00590     }
00591     
00592     /* if a '/' stopped our loop, balance the counter */
00593     if (end) --cursor;
00594     
00595     *size=cursor;
00596     return real;
00597 }
00598 
00599 
00629 ssize_t keySetName(Key *key, const char *newName) {
00630     size_t length;
00631     size_t rootLength, userLength, systemLength, userDomainLength;
00632     size_t keyNameSize=1; /* equal to length plus room for \0 */
00633     char *p=0;
00634     size_t size=0;
00635     
00636     /* handle null new key name, removing the old key */
00637     if (!newName || !(length=strblen(newName)-1)) {
00638         if (key->key) {
00639             free(key->key);
00640             key->key=0;
00641         }
00642         key->flags &= ~(KEY_SWITCH_NAME | KEY_SWITCH_NEEDSYNC |
00643                 KEY_SWITCH_ISSYSTEM | KEY_SWITCH_ISUSER);
00644         return 0;
00645     }
00646 
00647     rootLength=keyNameGetFullRootNameSize(newName)-1;
00648     if (!rootLength) {
00649         errno=KDB_RET_INVALIDKEY;
00650         return -1;
00651     }
00652     userLength=sizeof("user")-1;
00653     systemLength=sizeof("system")-1;
00654     userDomainLength=rootLength-userLength;
00655     
00656     if (userDomainLength>0) --userDomainLength;
00657 
00658     if (keyNameIsUser(newName)) {
00659         /* handle "user*" */
00660         if (length > userLength) {
00661             /* handle "user?*" */
00662             if (*(newName+userLength)==':') {
00663                 /* handle "user:*" */
00664                 if (userDomainLength > 0) {
00665                     p=realloc(key->userDomain,userDomainLength+1);
00666                     if (NULL==p) goto error_mem;
00667                     key->userDomain=p;
00668                     strncpy(key->userDomain,newName+userLength+1,userDomainLength);
00669                     key->userDomain[userDomainLength]=0; 
00670                     key->flags |= KEY_SWITCH_DOMAIN;
00671                 }
00672                 keyNameSize+=length-userDomainLength-1;  /* -1 is for the ':' */
00673             } else if (*(newName+userLength)!=RG_KEY_DELIM) {
00674                 /* handle when != "user/ *" */
00675                 errno=KDB_RET_INVALIDKEY;
00676                 return -1;
00677             } else {
00678                 /* handle regular "user/ *" */
00679                 keyNameSize+=length;
00680             }
00681         } else {
00682             /* handle "user" */
00683             keyNameSize+=userLength;
00684         }
00685         
00686         if (!key->userDomain) {
00687             char *envVar;
00688 
00689             envVar = getenv("USER");
00690             if ( envVar ) {
00691                 keySetOwner(key, envVar);
00692             } else {
00693                     /* TODO: handle "can't find $USER envar" */
00694                 keySetOwner(key, NULL);
00695                 }
00696         }
00697 
00698         rootLength  = userLength;
00699         key->flags |= KEY_SWITCH_ISUSER;
00700         key->flags &= ~KEY_SWITCH_ISSYSTEM;
00701     } else if (keyNameIsSystem(newName)) {
00702         /* handle "system*" */
00703         if (length > systemLength && *(newName+systemLength)!=RG_KEY_DELIM) {
00704             /* handle when != "system/ *" */
00705             errno=KDB_RET_INVALIDKEY;
00706             return -1;
00707         }
00708         keyNameSize+=length;
00709         
00710         rootLength  = systemLength;
00711         key->flags |= KEY_SWITCH_ISSYSTEM;
00712         key->flags &= ~KEY_SWITCH_ISUSER;
00713     } else {
00714         /* Given newName is neither "system" or "user" */
00715         errno=KDB_RET_INVALIDKEY;
00716         return -1;
00717     }
00718     
00719     /*
00720        At this point:
00721        - key->key has no memory (re)allocated yet
00722        - keyNameSize has number of bytes that will be allocated for key name
00723          with already removed user domain (in case of newName contained
00724          a domain)
00725        - key->userDomain is already set if newName is "user*"
00726        - rootLength is sizeof("user")-1 or sizeof("system")-1
00727     */
00728 
00729     /* Allocate memory for key->key */
00730     p=malloc(keyNameSize);
00731     if (NULL==p) goto error_mem;
00732     if (key->key) free(key->key);
00733     key->key=p;
00734 
00735     /* here key->key must have a correct size allocated buffer */
00736     if (!key->key) return -1;
00737 
00738     /* copy the root of newName to final destiny */
00739     strncpy(key->key,newName,rootLength);
00740     
00741     /* skip the root */
00742     p=(char *)newName;
00743     size=0;
00744     p=keyNameGetOneLevel(p+size,&size);
00745     
00746     /* iterate over each single folder name removing repeated '/' and escaping when needed */
00747     keyNameSize=rootLength;
00748     while (*(p=keyNameGetOneLevel(p+size,&size))) {
00749         /* Add a '/' to the end of key name */
00750         key->key[keyNameSize]=RG_KEY_DELIM;
00751         keyNameSize++;
00752         
00753         /* carefully append basenames */
00754         memcpy(key->key+keyNameSize,p,size);
00755         keyNameSize+=size;
00756     }
00757     key->key[keyNameSize]=0; /* finalize string */
00758 
00759     key->flags |= KEY_SWITCH_NAME | KEY_SWITCH_NEEDSYNC;
00760     
00761     return keyNameSize+1;
00762 
00763     error_mem:
00764         errno=KDB_RET_NOMEM;
00765         return -1;
00766 }
00767 
00768 
00769 
00770 
00786 ssize_t keyAddBaseName(Key *key,const char *baseName) {
00787     size_t nameSize=0;
00788     size_t newSize=0;
00789     size_t size=0;
00790     char *p=0;
00791 
00792     if (key->key) nameSize=strblen(key->key);
00793     if (baseName) newSize=strblen(baseName);
00794     else return nameSize;
00795     
00796     /* At this point, newSize has size of the baseName string, +1 for NULL */
00797     
00798     if (newSize <= 1)
00799         /* baseName is empty or NULL, so we are done */
00800         return nameSize;
00801     
00802     if (key->key) {
00803         p=realloc(key->key,newSize+nameSize);
00804         if (NULL == p) {
00805             errno=KDB_RET_NOMEM;
00806             return -1;
00807         }
00808         
00809         /*strcpy(p,key->key);
00810         free(key->key); key->key=0;*/
00811         key->key=p;
00812         
00813         /* Start appending basenames */
00814         p=(char *)baseName;
00815         nameSize--;
00816         while (*(p=keyNameGetOneLevel(p+size,&size))) {
00817             /* Add a '/' to the end of key name */
00818             key->key[nameSize]=RG_KEY_DELIM;
00819             nameSize++;
00820         
00821             /* carefully append basenames */
00822             memcpy(key->key+nameSize,p,size);
00823             nameSize+=size;
00824         }
00825         key->key[nameSize]=0; /* finalize string */
00826         return nameSize+1;
00827     } else return keySetName(key,baseName);
00828 }
00829 
00830 
00831 
00832 
00849 ssize_t keySetBaseName(Key *key, const char *baseName) {
00850     size_t newSize=0;
00851     size_t size=0;
00852     char *p=0;
00853     char *prevParent=0;
00854     size_t parentSize=0;
00855     size_t oldSize=0;
00856 
00857     if (baseName) newSize=strblen(baseName);
00858     
00859     /* Consume entire parent name */
00860     p=key->key;
00861     while (*(p=keyNameGetOneLevel(p+size,&size)))
00862         prevParent=p;
00863 
00864     if (prevParent && prevParent!=key->key) {
00865         /* For a key like "abc/def/ghi/jkl" prevParent is now pointing
00866            to the 'j'. Move it to previous char, which is probably '/'. */
00867         --prevParent;
00868     
00869         oldSize=strblen(key->key);
00870         parentSize = prevParent-key->key;
00871     
00872         /* For a key like "abc/def/ghi/jkl" parentSize now has size 11 which
00873            is number of bytes from 'a' to 'i' */
00874     
00875         /* Strip old "/basename" */
00876         key->key[parentSize]=0;
00877     
00878         /* baseName is empty or NULL, so we are done */
00879         if (newSize <= 1) return parentSize+1;
00880         
00881         /* Check if we need to extend memory allocated for key->key */
00882         if (oldSize < (newSize += parentSize + 1)) {
00883             p=realloc(key->key,newSize);
00884             if (NULL == p) {
00885                 errno=KDB_RET_NOMEM;
00886                 return -1;
00887             }
00888         
00889             key->key=p;
00890         }
00891         
00892         /* Start appending basenames */
00893         size=0;
00894         p=(char *)baseName;
00895         while (*(p=keyNameGetOneLevel(p+size,&size))) {
00896             /* Add a '/' to the end of key name */
00897             key->key[parentSize]=RG_KEY_DELIM;
00898             parentSize++;
00899         
00900             /* carefully append basenames */
00901             memcpy(key->key+parentSize,p,size);
00902             parentSize+=size;
00903         }
00904         key->key[parentSize]=0; /* finalize string */
00905         return parentSize+1;
00906     } else return keySetName(key,baseName);
00907 }
00908 
00909 
00910 
00911 
00920 ssize_t keyGetNameSize(const Key *key) {
00921     if (key->key) return strblen(key->key);
00922     else return 0;
00923 }
00924 
00925 
00926 
00927 
00938 ssize_t keyGetName(const Key *key, char *returnedName, size_t maxSize) {
00939     size_t bytes;
00940 
00941     if (!key->key) {
00942         errno=KDB_RET_NOKEY;
00943         returnedName[0]=0;
00944         return 0;
00945     }
00946 
00947     bytes=strblen(strncpy(returnedName,key->key,maxSize));
00948     if (maxSize < strblen(key->key)) {
00949         errno=KDB_RET_TRUNC;
00950         return -1;
00951     }
00952     return bytes;
00953 }
00954 
00955 
00956 
00968 char *keyStealName(const Key *key) {
00969     return key->key;
00970 }
00971 
00972 
00973 
00974 
00975 
00976 
00984 ssize_t keyGetFullNameSize(const Key *key) {
00985     size_t returnedSize;
00986 
00987     if (!key->key) return 0;
00988 
00989     returnedSize=strblen(key->key);
00990 
00991     if (keyNameIsUser(key->key) && key->userDomain)
00992         returnedSize+=strblen(key->userDomain);
00993 
00994     /*
00995        After 2 strblen() calls looks like we counted one more NULL.
00996        But we need this byte count because a full key name has an
00997        additional ':' char.
00998     */
00999     
01000     return returnedSize;
01001 }
01002 
01003 
01004 
01005 
01015 ssize_t keyGetFullName(const Key *key, char *returnedName, size_t maxSize) {
01016     size_t userSize=sizeof("user")-1;
01017     size_t userDomainSize;
01018     ssize_t length;
01019     char *cursor;
01020 
01021     length=keyGetFullNameSize(key);
01022     if (length == 0) {
01023         errno=KDB_RET_NOKEY;
01024         returnedName[0]=0;
01025         return length;
01026     }
01027     if (length < 0) return length;
01028     if (length > maxSize) {
01029         errno=KDB_RET_TRUNC;
01030         return -1;
01031     }
01032 
01033     cursor=returnedName;
01034     if (keyIsUser(key)) {
01035         strncpy(cursor,key->key,userSize);
01036         cursor+=userSize;
01037         if (key->userDomain) {
01038             *cursor=':'; ++cursor;
01039             userDomainSize=strblen(key->userDomain)-1;
01040             strcpy(cursor,key->userDomain);
01041             cursor+=userDomainSize;
01042         }
01043         strcpy(cursor,key->key+userSize);
01044     } else strcpy(cursor,key->key);
01045 
01046     return length;
01047 }
01048 
01049 
01050 
01051 
01052 
01064 int keyNameGetNamespace(const char *keyName) {
01065     if (keyNameIsSystem(keyName)) return KEY_NS_SYSTEM;
01066     if (keyNameIsUser(keyName)) return KEY_NS_USER;
01067     return 0;
01068 }
01069 
01070 
01071 
01082 int keyGetNamespace(const Key *key) {
01083     if (key->flags & KEY_SWITCH_ISSYSTEM) return KEY_NS_SYSTEM;
01084     if (key->flags & KEY_SWITCH_ISUSER) return KEY_NS_USER;
01085     return 0;
01086 }
01087 
01088 
01089 
01099 int keyNameIsSystem(const char *keyName) {
01100     if (!strncmp("system",keyName,sizeof("system")-1)) return 1;
01101     return 0;
01102 }
01103 
01104 
01105 
01114 int keyIsSystem(const Key *key) {
01115     return (key->flags & KEY_SWITCH_ISSYSTEM)?1:0;
01116 }
01117 
01118 
01119 
01129 int keyNameIsUser(const char *keyName) {
01130     if (!strncmp("user",keyName,sizeof("user")-1)) return 1;
01131     return 0;
01132 }
01133 
01134 
01135 
01144 int keyIsUser(const Key *key) {
01145     return (key->flags & KEY_SWITCH_ISUSER)?1:0;
01146 }
01147 
01148 
01149 
01160 ssize_t keyNameGetFullRootNameSize(const char *keyName) {
01161     char *end;
01162     int length=strlen(keyName);
01163 
01164     if (!length) return 0;
01165 
01166     /*
01167         Possible situations:
01168         user:someuser
01169         user:someuser/
01170         user:someuser/key/name
01171         user:some.user/key/name
01172         .
01173         \.
01174         (empty)
01175     */
01176     end=strchr(keyName,RG_KEY_DELIM);
01177     if (!end) /* Reached end of string. Root is entire key. */
01178         end = (char *)keyName + length;
01179 
01180     return end-keyName+1;
01181 }
01182 
01183 
01184 
01195 ssize_t keyGetRootNameSize(const Key *key) {
01196     if (!key->key) return 0;
01197 
01198     if (keyIsUser(key)) return sizeof("user");
01199     else return sizeof("system");
01200 }
01201 
01202 
01203 
01221 ssize_t keyGetRootName(const Key *key, char *returned, size_t maxSize) {
01222     size_t size;
01223 
01224     if (!key->key) {
01225         errno=KDB_RET_NOKEY;
01226         return -1;
01227     }
01228 
01229     if (!(size=keyGetRootNameSize(key))) {
01230         errno=KDB_RET_NOKEY;
01231         return -1;
01232     }
01233 
01234     if (maxSize < size) {
01235         errno=KDB_RET_TRUNC;
01236         return -1;
01237     } else strncpy(returned,key->key,size-1);
01238     returned[size-1]=0; /* null terminate it */
01239     return size;
01240 }
01241 
01242 
01243 
01244 
01245 
01246 
01262 ssize_t keyNameGetRootNameSize(const char *keyName) {
01263     int length=strlen(keyName);
01264 
01265     if (!length) return 0;
01266 
01267     /*
01268         Possible situations:
01269     user
01270     user/
01271     user/blabla
01272     user:someuser
01273     user:someuser/
01274     user:someuser/key/name
01275     system
01276     system/
01277     system/blabla
01278     (empty)
01279     */
01280     
01281     if (keyNameIsUser(keyName)) return sizeof("user");
01282     else if (keyNameIsSystem(keyName)) return sizeof("system");
01283     else {
01284         errno=KDB_RET_INVALIDKEY;
01285         return -1;
01286     }
01287 }
01288 
01289 
01290 
01291 
01292 
01304 ssize_t keyGetFullRootNameSize(const Key *key) {
01305     size_t size=0;
01306 
01307     if (keyIsUser(key)) {
01308         if (key->userDomain) size=strblen(key->userDomain);
01309         else size=strblen(getenv("USER"));
01310         
01311         return size+sizeof("user");
01312     } else {
01313         return keyNameGetRootNameSize(key->key);
01314     }
01315 }
01316 
01317 
01335 ssize_t keyGetFullRootName(const Key *key, char *returned, size_t maxSize) {
01336     size_t size;
01337     size_t rootSize;
01338     char *cursor;
01339 
01340     if (!key->key) {
01341         errno=KDB_RET_NOKEY;
01342         return 0;
01343     }
01344 
01345     if (!(size=keyGetFullRootNameSize(key))) {
01346         errno=KDB_RET_NOKEY;
01347         return 0;
01348     }
01349 
01350     if (maxSize < size) {
01351         errno=KDB_RET_TRUNC;
01352         return -1;
01353     }
01354     
01355     rootSize = keyGetRootNameSize(key)-1;
01356     strncpy(returned,key->key, rootSize); /* copy "user" or "system" */
01357     if (keyIsUser(key)) {
01358         cursor = returned + rootSize;
01359         *cursor = ':'; cursor++;
01360         if (key->userDomain)
01361             strncpy (cursor, key->userDomain, size - rootSize);
01362         else
01363             strncpy (cursor, getenv("USER"),  size - rootSize);
01364     } else {
01365         returned[rootSize]=0;
01366     }
01367 
01368     return size;
01369 }
01370 
01371 
01372 
01373 
01374 
01375 
01383 ssize_t keyGetParentNameSize(const Key *key) {
01384     char *parentNameEnd=0;
01385     char *p;
01386     size_t size;
01387 
01388     if (!key->key) {
01389         errno=KDB_RET_NOKEY;
01390         return 0;
01391     }
01392 
01393     /*
01394         user   (size=0)
01395         user/parent/base       (size=sizeof("user/parent"))
01396         user/parent/base/      (size=sizeof("user/parent"))
01397         user/parent/base\/name (size=sizeof("user/parent"))
01398     */
01399 
01400     /* initialize */
01401     p=key->key;
01402     size=0;
01403     
01404     /* iterate over level names */
01405     while (*(p=keyNameGetOneLevel(p+size,&size))) parentNameEnd=p;
01406     
01407     /* handle NULL or root key ("user" or "system") */
01408     if (!parentNameEnd || parentNameEnd==key->key) return 0;
01409 
01410     /* at this point, parentNameEnd points to the first char of the basename */
01411     /* example: it points to the 'b' of "user/key/basename" */
01412     
01413     /* the delta is the size we want */
01414     return parentNameEnd - key->key;
01415 }
01416 
01417 
01418 
01439 ssize_t keyGetParentName(const Key *key, char *returnedParent, size_t maxSize) {
01440     ssize_t parentSize;
01441 
01442     parentSize=keyGetParentNameSize(key);
01443 
01444     if (parentSize > maxSize) {
01445         errno=KDB_RET_TRUNC;
01446         return 0;
01447     } else strncpy(returnedParent,key->key,parentSize);
01448 
01449     returnedParent[parentSize-1]=0; /* ending NULL */
01450     
01451     return parentSize;
01452 }
01453 
01454 
01455 
01456 
01457 
01458 
01475 ssize_t keyNameGetBaseNameSize(const char *keyName) {
01476     char *p=(char *)keyName;
01477     char *base=0;
01478     size_t size=0;
01479     size_t baseSize=0;
01480     
01481     while (*(p=keyNameGetOneLevel(p+size,&size))) {
01482         base=p;
01483         baseSize=size;
01484     }
01485     
01486     if (base == keyName) return 0;
01487     else return baseSize+1;
01488 }
01489 
01490 
01491 
01506 ssize_t keyGetBaseNameSize(const Key *key) {
01507     if (!key->key) return 0;
01508 
01509     return keyNameGetBaseNameSize(key->key);
01510 }
01511 
01512 
01513 
01529 ssize_t keyGetBaseName(const Key *key, char *returned, size_t maxSize) {
01530     size_t size=0;
01531     char *p=key->key;
01532     char *baseName=0;
01533     size_t baseSize=0;
01534 
01535     while (*(p=keyNameGetOneLevel(p+size,&size))) {
01536         baseName=p;
01537         baseSize=size+1;
01538     }
01539     
01540     if (!baseName || baseName==key->key) return 0;
01541 
01542     if (maxSize < baseSize) {
01543         strncpy(returned,baseName,maxSize);
01544         errno=KDB_RET_TRUNC;
01545         return maxSize;
01546     } else {
01547         strncpy(returned,baseName,baseSize);
01548         return baseSize;
01549     }
01550 }
01551 
01552 
01562 char *keyStealBaseName(const Key *key) {
01563     char *p=key->key;
01564     char *base=0;
01565     size_t size=0;
01566     
01567     while (*(p=keyNameGetOneLevel(p+size,&size))) base=p;
01568     
01569     if (base != key->key) return base;
01570     else return 0;
01571 }
01572 
01573 
01574 /******************************************* 
01575  *    General value manipulation methods   *
01576  *******************************************/
01577 
01578 
01579 
01580 
01586 ssize_t keyGetDataSize(const Key *key) {
01587     return keyGetValueSize(key);
01588 }
01589 
01590 
01591 
01602 ssize_t keyGetValueSize(const Key *key) {
01603     return key->dataSize;
01604 }
01605 
01606 
01607 
01625 ssize_t keySetString(Key *key, const char *newStringValue) {
01626     ssize_t ret=newStringValue?strblen(newStringValue):0;
01627 
01628     if (!newStringValue || !ret) ret=keySetRaw(key,0,0);
01629     else ret=keySetRaw(key,newStringValue,ret);
01630 
01631     keySetType(key,KEY_TYPE_STRING);
01632 
01633     return ret;
01634 }
01635 
01636 
01637 
01662 ssize_t keyGetString(const Key *key, char *returnedString, size_t maxSize) {
01663     if (!key->data) {
01664         *returnedString=0;
01665         errno=KDB_RET_NODATA;
01666         return 0;
01667     }
01668 
01669     if (key->dataSize > maxSize) {
01670         errno=KDB_RET_TRUNC;
01671         return -1;
01672     }
01673 
01674     if (key->type < KEY_TYPE_STRING) {
01675         errno=KDB_RET_TYPEMISMATCH;
01676         return -1;
01677     }
01678 
01679     strcpy(returnedString,key->data);
01680     return key->dataSize;
01681 }
01682 
01683 
01684 
01685 
01686 
01687 
01737 void *keyStealValue(const Key *key) {
01738     return key->data;
01739 }
01740 
01741 
01742 
01743 
01744 
01745 
01746 
01747 
01757 ssize_t keySetLink(Key *key, const char *target) {
01758     ssize_t ret=target?strblen(target):0;
01759 
01760     if (!target || !ret) ret=keySetRaw(key,0,0);
01761     else ret=keySetRaw(key,target,ret);
01762 
01763     keySetType(key,KEY_TYPE_LINK);
01764 
01765     return ret;
01766 }
01767 
01768 
01769 
01781 ssize_t keyGetLink(const Key *key, char *returnedTarget, size_t maxSize) {
01786     if (!key->data) {
01787         errno=KDB_RET_NODATA;
01788         return 0;
01789     }
01790 
01791     if (key->type != KEY_TYPE_LINK) {
01792         errno=KDB_RET_TYPEMISMATCH;
01793         return -1;
01794     }
01795 
01796     if (key->dataSize > maxSize) {
01797         errno=KDB_RET_TRUNC;
01798         return -1;
01799     }
01800 
01801     strcpy(returnedTarget,key->data);
01802     return key->dataSize;
01803 }
01804 
01805 
01806 
01816 int keyIsLink(const Key *key) {
01817     return (key->type==KEY_TYPE_LINK);
01818 }
01819 
01820 
01821 
01831 int keyIsDir(const Key *key) {
01832     return (key->access & 0040000); /*S_IFDIR*/
01833     /* return key->type==KEY_TYPE_DIR; */
01834 }
01835 
01836 
01837 
01845 int keyIsBin(const Key *key) {
01846     return (KEY_TYPE_BINARY <= key->type && key->type < KEY_TYPE_STRING);
01847 }
01848 
01849 
01857 int keyIsString(const Key *key) {
01858     return (key->type >= KEY_TYPE_STRING);
01859 }
01860 
01861 
01862 
01863 
01873 ssize_t keyGetBinary(const Key *key, void *returnedValue, size_t maxSize) {
01874     if (!key->data) {
01875         errno=KDB_RET_NODATA;
01876         return 0;
01877     }
01878 
01879     if (key->dataSize > maxSize) {
01880         errno=KDB_RET_TRUNC;
01881         return -1;
01882     }
01883 
01884     memcpy(returnedValue,key->data,key->dataSize);
01885     return key->dataSize;
01886 }
01887 
01888 
01889 
01908 ssize_t keySetBinary(Key *key, const void *newBinary, size_t dataSize) {
01909     ssize_t ret=keySetRaw(key,newBinary,dataSize);
01910 
01911     keySetType(key,KEY_TYPE_BINARY);
01912 
01913     return ret;
01914 }
01915 
01916 
01917 
01926 int keyNeedsSync(const Key *key) {
01927     /* if (!key) return 0; */
01928     return (key->flags & KEY_SWITCH_NEEDSYNC);
01929 }
01930 
01931 
01932 
01942 uint8_t keyGetType(const Key *key) {
01943     return key->type;
01944 }
01945 
01946 
01947 
02019 uint8_t keySetType(Key *key,uint8_t newType) {
02020     mode_t mask=0;
02021 
02022     switch (newType) {
02023         case KEY_TYPE_DIR:
02024             mask=umask(0); umask(mask);
02025             keySetDir(key,mask);
02026             break;
02027         default:
02028             key->type=newType;
02029             /* key->access &= ~(0040000 | dirSwitch); */
02030             /*remove directory bits and dirSwitch*/
02031     }
02032     key->flags |= KEY_SWITCH_NEEDSYNC;
02033     return key->type;
02034 }
02035 
02036 
02063 uint8_t keySetDir(Key *key, mode_t customUmask) {
02064     mode_t dirSwitch=0111;
02065     
02066     /* key->type=KEY_TYPE_DIR; */
02067     key->access|=(dirSwitch & ~customUmask) | 0040000; /*S_IFDIR*/
02068     /* keySetRaw(key,0,0); remove data */
02069     
02070     key->flags |= KEY_SWITCH_NEEDSYNC;
02071     
02072     return KEY_TYPE_DIR;
02073 }
02074 
02075 
02088 ssize_t keySetRaw(Key *key, const void *newBinary, size_t dataSize) {
02089     if (!dataSize || !newBinary) {
02090         if (key->data) {
02091             free(key->data);
02092             key->data=0;
02093         }
02094         key->dataSize = 0;
02095         key->flags &= ~(KEY_SWITCH_VALUE);
02096         key->flags |= KEY_SWITCH_NEEDSYNC;
02097         return 0;
02098     }
02099 
02100     key->dataSize=dataSize;
02101     if (key->data) {
02102         char *p=0;
02103         p=realloc(key->data,key->dataSize);
02104         if (NULL==p) return -1;
02105         key->data=p;
02106     } else {
02107         key->data=malloc(key->dataSize);
02108         }
02109 
02110     if (!key->data) return -1;
02111 
02112     memcpy(key->data,newBinary,key->dataSize);
02113     key->flags |= KEY_SWITCH_VALUE | KEY_SWITCH_NEEDSYNC;
02114     return key->dataSize;
02115 }
02116 
02117 
02118 
02119 
02120 
02121 
02122 
02123 
02124 /***************************************************** 
02125  *    General owner or domain manipulation methods   *
02126  *****************************************************/
02127 
02128 
02129 
02141 ssize_t keySetOwner(Key *key, const char *userDomain) {
02142     ssize_t size;
02143 
02144     if (userDomain == 0) {
02145         if (key->userDomain) {
02146             free(key->userDomain);
02147             key->userDomain=0;
02148         }
02149         key->flags &= ~KEY_SWITCH_DOMAIN;
02150         return 0;
02151     }
02152 
02153     if ((size=strblen(userDomain)) > 0) {
02154         if (key->userDomain) {
02155             char *p=0;
02156             p=realloc(key->userDomain,size);
02157             if (NULL==p) {
02158                 errno=KDB_RET_NOMEM;
02159                 return -1;
02160             }
02161             key->userDomain=p;
02162         } else {
02163             key->userDomain=malloc(size);
02164         }
02165         if (!key->userDomain) return -1; /* propagate errno */
02166 
02167         strcpy(key->userDomain,userDomain);
02168         key->flags |= KEY_SWITCH_DOMAIN | KEY_SWITCH_NEEDSYNC;
02169         return size;
02170     } else if (key->userDomain) {
02171         free(key->userDomain);
02172         key->userDomain=0;
02173         key->flags &= ~(KEY_SWITCH_DOMAIN | KEY_SWITCH_NEEDSYNC);
02174     }
02175     return 0;
02176 }
02177 
02178 
02179 
02187 ssize_t keyGetOwnerSize(const Key *key) {
02188     if (!key->userDomain) {
02189         errno=KDB_RET_NODOMAIN;
02190         return 0;
02191     }
02192 
02193     return strblen(key->userDomain);
02194 }
02195 
02196 
02197 
02218 ssize_t keyGetOwner(const Key *key, char *returned, size_t maxSize) {
02219     ssize_t bytes;
02220 
02221     if (!key->userDomain) {
02222         errno=KDB_RET_NODOMAIN;
02223         return 0;
02224     }
02225 
02226     if (maxSize < (bytes=strblen(key->userDomain))) {
02227         errno=KDB_RET_TRUNC;
02228         return -1;
02229     } else strcpy(returned,key->userDomain);
02230     return bytes;
02231 }
02232 
02233 
02234 
02235 
02245 char *keyStealOwner(const Key *key) {
02246     return key->userDomain;
02247 }
02248 
02249 
02250 
02251 
02252 
02253 
02254 /********************************************* 
02255  *    General comment manipulation methods   *
02256  *********************************************/
02257 
02258 
02259 
02271 ssize_t keySetComment(Key *key, const char *newComment) {
02272     ssize_t size;
02273 
02274     if (newComment && (size=strblen(newComment)) > 0) {
02275         if (key->flags & KEY_SWITCH_COMMENT) {
02276             char *p=0;
02277             p=realloc(key->comment,size);
02278             if (NULL==p) {
02279                 errno=KDB_RET_NOMEM;
02280                 return -1;
02281             }
02282             key->comment=p;
02283         } else {
02284             key->comment=malloc(size);
02285         }
02286         if (!key->comment) return -1;
02287 
02288         strcpy(key->comment,newComment);
02289         key->flags |= KEY_SWITCH_COMMENT | KEY_SWITCH_NEEDSYNC;
02290         return key->commentSize=size;
02291     } else if (key->flags & KEY_SWITCH_COMMENT) {
02292         free(key->comment);
02293         key->comment=0;
02294         key->flags &= ~(KEY_SWITCH_COMMENT | KEY_SWITCH_NEEDSYNC);
02295     }
02296     return key->commentSize=0;
02297 }
02298 
02299 
02300 
02311 ssize_t keyGetCommentSize(const Key *key) {
02312     if (!key->comment) {
02313         errno=KDB_RET_NODESC;
02314         return 0;
02315     }
02316 
02317     return strblen(key->comment);
02318 }
02319 
02320 
02321 
02333 ssize_t keyGetComment(const Key *key, char *returnedDesc, size_t maxSize) {
02334     ssize_t bytes;
02335 
02336     if (!key->comment) {
02337         errno=KDB_RET_NODESC;
02338         return 0;
02339     }
02340 
02341     bytes=strblen(strncpy(returnedDesc,key->comment,maxSize));
02342     if (maxSize < strblen(key->comment)) {
02343         errno=KDB_RET_TRUNC;
02344         return -1;
02345     }
02346     return bytes;
02347 }
02348 
02349 
02360 char *keyStealComment(const Key *key) {
02361     return key->comment;
02362 }
02363 
02364 
02365 
02366 
02367 /*********************************************
02368  *    UID, GID and ACL bits methods          *
02369  *********************************************/
02370 
02371 
02372 
02383 uid_t keyGetUID(const Key *key) {
02384     return key->uid;
02385 }
02386 
02387 
02388 
02399 int keySetUID(Key *key, uid_t uid) {
02400     key->uid=uid;
02401     key->flags |= KEY_SWITCH_UID | KEY_SWITCH_NEEDSYNC;
02402 
02403     return 0;
02404 }
02405 
02406 
02407 
02415 gid_t keyGetGID(const Key *key) {
02416     return key->gid;
02417 }
02418 
02419 
02420 
02428 int keySetGID(Key *key, gid_t gid) {
02429     key->gid=gid;
02430     key->flags |= KEY_SWITCH_GID | KEY_SWITCH_NEEDSYNC;
02431 
02432     return 0;
02433 }
02434 
02435 
02436 
02442 mode_t keyGetAccess(const Key *key) {
02443     return key->access;
02444 }
02445 
02446 
02447 
02458 int keySetAccess(Key *key, mode_t mode) {
02459     key->access=mode;
02460     key->flags |= KEY_SWITCH_MODE | KEY_SWITCH_NEEDSYNC;
02461 
02462     return 0;
02463 }
02464 
02465 
02466 
02467 
02468 
02479 int keySetUAccess(Key *key, mode_t umask) {
02480     key->access=DEFFILEMODE & ~umask;
02481 
02482     key->flags |= KEY_SWITCH_MODE | KEY_SWITCH_NEEDSYNC;
02483 
02484     return 0;
02485 }
02486 
02487 
02488 
02489 
02490 /*********************************************
02491  *    Access times methods                   *
02492  *********************************************/
02493 
02494 
02499 time_t keyGetMTime(const Key *key) {
02500     return key->mtime;
02501 }
02502 
02503 
02504 
02509 time_t keyGetATime(const Key *key) {
02510     return key->atime;
02511 }
02512 
02513 
02514 
02519 time_t keyGetCTime(const Key *key) {
02520     return key->ctime;
02521 }
02522 
02523 
02524 
02525 
02526 
02527 
02528 /*********************************************
02529  *    Other methods                          *
02530  *********************************************/
02531 
02532 
02533 
02534 ssize_t keyGetRecordSize(const Key *key) {
02535     return key->recordSize;
02536 }
02537 
02538 
02544 Key *keyNext(Key *key) {
02545     return key->next;
02546 }
02547 
02548 
02549 
02550 
02551 
02552 
02553 
02554 
02572 int keyDup(const Key *source, Key *dest) {
02573 
02574     /* Copy the struct data, including the "next" pointer */
02575     *dest=*source;
02576 
02577     /* prepare to set dynamic properties */
02578     dest->key=
02579             dest->comment=
02580             dest->userDomain=
02581             dest->data=0;
02582 
02583     /* TODO: handle errors, mostly due to memory allocation */
02584     /* Set properties that need memory allocation */
02585     keySetName(dest,source->key);
02586     keySetOwner(dest,source->userDomain);
02587     keySetComment(dest,source->comment);
02588     keySetRaw(dest,source->data,source->dataSize);
02589 
02590     dest->flags=source->flags | KEY_SWITCH_NEEDSYNC;
02591     
02592     return 0;
02593 }
02594 
02595 
02596 
02597 
02598 
02691 uint32_t keyCompare(const Key *key1, const Key *key2) {
02692     uint32_t ret=0;
02693 
02694 
02695     /* Compare these numeric properties */
02696     if (key1->uid != key2->uid)                    ret|=KEY_SWITCH_UID;
02697     if (key1->gid != key2->gid)                    ret|=KEY_SWITCH_GID;
02698     if (key1->type != key2->type)                  ret|=KEY_SWITCH_TYPE;
02699 #if defined(S_IRWXU) && defined(S_IRWXG) && defined(S_IRWXO)
02700     if ((key1->access & (S_IRWXU|S_IRWXG|S_IRWXO)) !=
02701         (key2->access & (S_IRWXU|S_IRWXG|S_IRWXO))) ret|=KEY_SWITCH_MODE;
02702 #else
02703     if ((key1->access) !=
02704         (key2->access)) ret|=KEY_SWITCH_MODE;
02705 #endif
02706 
02707     /* Compare these string properties.
02708        A lot of decisions because strcmp can't handle NULL pointers */
02709     if (key1->key && key2->key) {
02710         if (strcmp(key1->key,key2->key))            ret|=KEY_SWITCH_NAME;
02711     } else
02712         if (key1->key || key2->key)                 ret|=KEY_SWITCH_NAME;
02713 
02714     if (key1->comment && key2->comment) {
02715         if (strcmp(key1->comment,key2->comment))    ret|=KEY_SWITCH_COMMENT;
02716     } else
02717         if (key1->comment || key2->comment)         ret|=KEY_SWITCH_COMMENT;
02718 
02719     if (key1->userDomain && key2->userDomain) {
02720         if (strcmp(key1->userDomain,key2->userDomain)) ret|=KEY_SWITCH_DOMAIN;
02721     } else
02722         if (key1->userDomain || key2->userDomain)      ret|=KEY_SWITCH_DOMAIN;
02723 
02724     /* select and compare some flags */
02725     ret|=
02726         /* put in evidence the differences only */
02727         (key1->flags ^ key2->flags) &
02728         /* and compare with what we need */
02729         (KEY_SWITCH_FLAG | KEY_SWITCH_NEEDSYNC);
02730     
02731     /* Compare data */
02732     if (key1->dataSize != key2->dataSize)          ret|=KEY_SWITCH_VALUE;
02733     else if (memcmp(key1->data,key2->data,
02734             (key1->dataSize<=key2->dataSize?key1->dataSize:key2->dataSize)))
02735                                                    ret|=KEY_SWITCH_VALUE;
02736 
02737     return ret;
02738 }
02739 
02740 
02741 
02742 
02743 
02744 
02745 /*********************************************
02746  *    Textual XML methods                    *
02747  *********************************************/
02748 
02749 
02786 ssize_t keyToStream(const Key *key, FILE* stream, unsigned long options) {
02787     return keyToStreamBasename(key,stream,0,0,options);
02788 }
02789 
02790 
02791 
02792 
02793 
02832 ssize_t keyToStreamBasename(const Key *key, FILE *stream, const char *parent,
02833         const size_t parentSize, unsigned long options) {
02834     ssize_t written=0;
02835     char buffer[800];
02836     struct passwd *pwd=0;
02837     struct group *grp=0;
02838 
02839     /* Write key name */
02840     if (parent) {
02841         /* some logic to see if we should print only the relative basename */
02842         int found;
02843         size_t skip=parentSize ? parentSize : strblen(parent)-1;
02844 
02845         found=memcmp(parent,key->key,skip);
02846         if (found == 0) {
02847             while (*(key->key+skip) == RG_KEY_DELIM) ++skip;
02848 
02849             if (*(key->key+skip) != 0) /* we don't want a null basename */
02850                 written+=fprintf(stream,"<key basename=\"%s\"",
02851                     key->key+skip);
02852         }
02853     }
02854 
02855     if (written == 0) { /* no "<key basename=..." was written so far */
02856         if (options & KDB_O_FULLNAME) {
02857             keyGetFullName(key,buffer,sizeof(buffer));
02858             written+=fprintf(stream,"<key name=\"%s\"", buffer);
02859         } else written+=fprintf(stream,"<key name=\"%s\"", key->key);
02860     }
02861 
02862 
02863     if (options & KDB_O_CONDENSED) written+=fprintf(stream," ");
02864     else written+=fprintf(stream,"\n     ");
02865 
02866 
02867 
02868     /* Key type */
02869     if (options & KDB_O_NUMBERS) {
02870         written+=fprintf(stream,"type=\"%d\"", key->type);
02871     } else {
02872         buffer[0]=0;
02873 
02874         switch (key->type) {
02875             case KEY_TYPE_STRING:
02876                 strcpy(buffer,"string");
02877                 break;
02878             case KEY_TYPE_BINARY:
02879                 strcpy(buffer,"binary");
02880                 break;
02881             case KEY_TYPE_LINK:
02882                 strcpy(buffer,"link");
02883                 break;
02884         /*  case KEY_TYPE_DIR:
02885                 strcpy(buffer,"directory");
02886                 break; */
02887             case KEY_TYPE_UNDEFINED:
02888                 strcpy(buffer,"undefined");
02889                 break;
02890         }
02891         if (buffer[0]) written+=fprintf(stream,"type=\"%s\"", buffer);
02892         else written+=fprintf(stream,"type=\"%d\"", key->type);
02893         
02894         written+=fprintf(stream," ");
02895         if (keyIsDir(key)) written+=fprintf(stream,"isdir=\"yes\"");
02896     }
02897 
02898 #ifdef HAVE_PWD_H
02899     if (keyIsUser(key)) {
02900         struct passwd *domainPwd=0;
02901         int uidMatch,gidMatch;
02902         
02903         domainPwd=getpwnam(key->userDomain);
02904         pwd=getpwuid(key->uid);
02905         grp=getgrgid(key->gid);
02906         
02907         uidMatch=(key->uid == domainPwd->pw_uid);
02908         gidMatch=(key->gid == domainPwd->pw_gid);
02909         
02910         if (options & KDB_O_FULLUGID) {
02911             if (pwd && !(options & KDB_O_NUMBERS))
02912                 written+=fprintf(stream," uid=\"%s\"",pwd->pw_name);
02913             else written+=fprintf(stream,   " uid=\"%d\"",key->uid);
02914         
02915             if (grp && !(options & KDB_O_NUMBERS))
02916                 written+=fprintf(stream," gid=\"%s\"",grp->gr_name);
02917             else written+=fprintf(stream," gid=\"%d\"",key->gid);
02918         } else {
02919             if (!uidMatch) {
02920                 if (pwd && !(options & KDB_O_NUMBERS))
02921                     written+=fprintf(stream," uid=\"%s\"",pwd->pw_name);
02922                 else written+=fprintf(stream,   " uid=\"%d\"",key->uid);
02923             }
02924 
02925             if (!gidMatch) {
02926                 if (grp && !(options & KDB_O_NUMBERS))
02927                     written+=fprintf(stream," gid=\"%s\"",grp->gr_name);
02928                 else written+=fprintf(stream,   " gid=\"%d\"",key->gid);
02929             }
02930         }
02931     } else {
02932         if (!(options & KDB_O_NUMBERS)) {
02933             pwd=getpwuid(key->uid);
02934             grp=getgrgid(key->gid);
02935         }
02936 
02937         /* UID, GID, mode */
02938         if (pwd) written+=fprintf(stream," uid=\"%s\"",pwd->pw_name);
02939         else  written+=fprintf(stream,   " uid=\"%d\"",key->uid);
02940 
02941         if (grp) written+=fprintf(stream," gid=\"%s\"",grp->gr_name);
02942         else  written+=fprintf(stream,   " gid=\"%d\"",key->gid);
02943     }
02944 #endif
02945 
02946 #if defined(S_IRWXU) && defined(S_IRWXG) && defined(S_IRWXO)
02947     written+=fprintf(stream," mode=\"0%o\"",
02948         key->access & (S_IRWXU|S_IRWXG|S_IRWXO));
02949 #else
02950     written+=fprintf(stream," mode=\"0%o\"",
02951         key->access);
02952 #endif
02953 
02954 
02955     if (!key->data && !key->comment) { /* no data AND no comment */
02956         written+=fprintf(stream,"/>");
02957         if (!(options & KDB_O_CONDENSED))
02958             written+=fprintf(stream,"\n\n\n\n\n\n");
02959         
02960         return written; /* end of <key/> */
02961     } else {
02962         if (key->data) {
02963             if ((key->dataSize <= 16) &&
02964                     key->type >= KEY_TYPE_STRING &&
02965                     !strchr(key->data,'\n')) {
02966 
02967                 /* we'll use a "value" attribute instead of a <value> node,
02968                    for readability, so the cut size will be 16, which is
02969                    the maximum size of an IPv4 address */
02970 
02971                 if (options & KDB_O_CONDENSED) written+=fprintf(stream," ");
02972                 else written+=fprintf(stream,"\n     ");
02973                 
02974                 written+=fprintf(stream,"value=\"%s\"",(char *)key->data);
02975                 
02976                 if (key->comment) written+=fprintf(stream,">\n");
02977                 else {
02978                     written+=fprintf(stream,"/>");
02979                     if (!(options & KDB_O_CONDENSED))
02980                         written+=fprintf(stream,"\n\n\n\n\n\n");
02981                 
02982                     return written;
02983                 }
02984             } else { /* value is bigger than 16 bytes: deserves own <value> */
02985                 written+=fprintf(stream,">");
02986                 if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n\n     ");
02987                 
02988                 written+=fprintf(stream,"<value>");
02989                 if (key->type >= KEY_TYPE_STRING || key->type < KEY_TYPE_BINARY) {
02990                     written+=fprintf(stream,"<![CDATA[");
02991                     fflush(stream);
02992                     /* must chop ending \0 */
02993                     written+=write(fileno(stream),key->data,key->dataSize-1);
02994                     written+=fprintf(stream,"]]>");
02995                 } else {
02996                     /* Binary values */
02997                     char *encoded=malloc(3*key->dataSize);
02998                     size_t encodedSize;
02999 
03000                     written+=fprintf(stream,"\n");
03001                     encodedSize=encode(key->data,key->dataSize,encoded);
03002                     fflush(stream);
03003                     written+=write(fileno(stream),encoded,encodedSize);
03004                     free(encoded);
03005                     written+=fprintf(stream,"\n");
03006                 }
03007                 /* fflush(stream); */
03008                 written+=fprintf(stream,"</value>");
03009             }
03010         } else { /* we have no data */
03011             if (key->comment) {
03012                 written+=fprintf(stream,">");
03013                 if (!(options & KDB_O_CONDENSED))
03014                     written+=fprintf(stream,"\n");
03015             } else {
03016                 written+=fprintf(stream,"/>");
03017                 if (!(options & KDB_O_CONDENSED))
03018                     written+=fprintf(stream,"\n\n\n\n\n\n");
03019             
03020                 return written;
03021             }
03022         }
03023     }
03024 
03025     if (!(options & KDB_O_CONDENSED)) {
03026         written+=fprintf(stream,"\n");
03027         if (key->comment) written+=fprintf(stream,"     ");
03028     }
03029 
03030     if (key->comment) {
03031         written+=fprintf(stream,"<comment><![CDATA[%s]]></comment>", key->comment);
03032         if (!(options & KDB_O_CONDENSED))
03033             written+=fprintf(stream,"\n");
03034     }
03035 
03036     written+=fprintf(stream,"</key>");
03037 
03038     if (!(options & KDB_O_CONDENSED))
03039         written+=fprintf(stream,"\n\n\n\n\n\n");
03040 
03041     return written;
03042 }
03043 
03044 
03045 /*
03046 size_t keyGetSerializedSizeWithoutName(Key *key) {
03047     return sizeof(KeyInfo)+
03048         key->dataSize+
03049         key->groupSize+
03050         key->commentSize;
03051 }
03052 */
03053 
03054 /*
03055 size_t keyGetSerializedSize(Key *key) {
03056     size_t totalSize;
03057 
03058     totalSize=(key->key)+1+keyGetSerializedSizeWithoutName(key);
03059     if (key->userDomain) totalSize+=strlen(key->userDomain)+1;
03060     return totalSize;
03061 }*/
03062 
03063 
03064 
03065 
03066 
03067 /*********************************************
03068  *    Flag manipulation methods              *
03069  *********************************************/
03070 
03071 
03072 
03073 
03085 int keySetFlag(Key *key) {
03086     key->flags|=KEY_SWITCH_FLAG;
03087 
03088     return 0;
03089 }
03090 
03091 
03092 
03104 int keyClearFlag(Key *key) {
03105     key->flags &= ~KEY_SWITCH_FLAG;
03106 
03107     return 0;
03108 }
03109 
03110 
03111 
03124 int keyGetFlag(const Key *key) {
03125     return (key->flags & KEY_SWITCH_FLAG) ? 1:0;
03126 }
03127 
03128 
03129 
03130 
03131 
03132 /*********************************************************************
03133  *    Key instance construction and destruction methods              *
03134  *********************************************************************/
03135 
03136 
03173 int keyInit(Key *key) {
03174     mode_t localUmask;
03175     
03176     memset(key,0,sizeof(Key));
03177     key->type=KEY_TYPE_UNDEFINED;
03178     
03179     /* If we lack the getuid() and getgid() functions we leave uid and gid at 0 */
03180     #if defined(HAVE_GETUID) && defined(HAVE_GETGID)
03181     key->uid=getuid();
03182     key->gid=getgid();
03183     #endif
03184     
03185     /* by default do this, but backends should take care to carefully set
03186        access permissions based on their handle */
03187     localUmask=umask(0); umask(localUmask);
03188     keySetUAccess(key,localUmask);
03189 
03190     key->flags = KEY_SWITCH_INITIALIZED;
03191 
03192     return 0;
03193 }
03194 
03195 
03196 
03197 
03218 int keyClose(Key *key) {
03219     if (key->key) free(key->key);
03220     if (key->data) free(key->data);
03221     if (key->comment) free(key->comment);
03222     if (key->userDomain) free(key->userDomain);
03223     memset(key,0,sizeof(Key));
03224     return 0;
03225 }
03226 
03227 
03236 void *keySerialize(Key *key) {
03237     size_t metaInfoSize=0;
03238     size_t fullNameSize=0;
03239     void *serialized=0;
03240     
03241     fullNameSize=keyGetFullNameSize(key);
03242     
03243     metaInfoSize = KEY_METAINFO_SIZE(key);
03244     
03245     key->recordSize=metaInfoSize + key->dataSize + key->commentSize
03246         + fullNameSize;
03247     serialized=malloc(key->recordSize);
03248     memset(serialized,0,key->recordSize);
03249     
03250     /* First part: the metainfo */
03251     memcpy(serialized,key,metaInfoSize);
03252     
03253     /* Second part: the comment */
03254     if (key->comment) memcpy((char *)(serialized)+metaInfoSize,
03255             key->comment,key->commentSize);
03256     
03257     /* Third part: the value */
03258     if (key->data) memcpy((char *)(serialized)+metaInfoSize+key->commentSize,
03259             key->data,key->dataSize);
03260     
03261     /* Fourth part: the full key name */
03262     keyGetFullName(key,
03263         (char *)(serialized)+metaInfoSize+key->commentSize+key->dataSize,
03264         fullNameSize);
03265     
03266     return serialized;
03267 }
03268 
03279 Key *keyUnserialize(const void *serialized) {
03280     Key *key=0;
03281     size_t metaInfoSize=0;
03282     
03283     if (!serialized) return 0;
03284     
03285     key=keyNew(KEY_SWITCH_END);
03286     
03287     /* First part: the metainfo */
03288     metaInfoSize = KEY_METAINFO_SIZE(key);
03289     memcpy(key,serialized,metaInfoSize);
03290     
03291     /* Second part: the comment */
03292     if (key->commentSize) {
03293         key->comment=malloc(key->commentSize);
03294         memcpy(key->comment,
03295             (char *)(serialized)+metaInfoSize,
03296             key->commentSize);
03297     }
03298     
03299     /* Third part: the value */
03300     if (key->dataSize) {
03301         key->data=malloc(key->dataSize);
03302         memcpy(key->data,
03303             (char *)(serialized)+metaInfoSize+key->commentSize,
03304             key->dataSize);
03305     }
03306     
03307     /* Fourth part: the full key name */
03308     keySetName(key,
03309         (char *)(serialized)+metaInfoSize+key->commentSize+key->dataSize);
03310     
03311     return key;
03312 }

Generated on Mon Dec 17 18:45:35 2007 for Elektra Project by  doxygen 1.5.4