backendhelpers.c

00001 /***************************************************************************
00002             helpers.c  -  Helpers for backends
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 
00017 
00018 
00019 /* Subversion stuff
00020 
00021 $Id: libkdb.c 736 2006-04-14 15:31:44Z aviram $
00022 
00023 */
00024 
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include "config.h"
00028 #endif
00029 
00030 #ifdef HAVE_UNISTD_H
00031 #include <unistd.h>
00032 #endif
00033 
00034 #ifdef HAVE_ICONV
00035 #include <iconv.h>
00036 #endif
00037 
00038 #ifdef HAVE_LOCALE_H
00039 #include <locale.h>
00040 #endif
00041 
00042 #ifdef HAVE_LANGINFO_H
00043 #include <langinfo.h>
00044 #endif
00045 
00046 #ifdef HAVE_SYS_TYPES_H
00047 #include <sys/types.h>
00048 #endif
00049 
00050 #ifdef HAVE_SYS_STAT_H
00051 #include <sys/stat.h>
00052 #endif
00053 
00054 #ifdef HAVE_SYS_TYPES_H
00055 #include <sys/types.h>
00056 #endif
00057 
00058 #ifdef HAVE_FCNTL_H
00059 #include <fcntl.h>
00060 #endif
00061 
00062 #ifdef HAVE_STDIO_H
00063 #include <stdio.h>
00064 #endif
00065 
00066 
00067 
00068 #include <stdlib.h>
00069 #include <stdarg.h>
00070 #include <ctype.h>
00071 #include <string.h>
00072 #include <errno.h>
00073 #include <stdio.h>
00074 #include <pthread.h>
00075 
00076 
00077 /* kdbbackend.h will include kdb.h and kdbprivate.h */
00078 #include "kdbbackend.h"
00079 #include "kdbLibLoader.h"
00080 
00081 /* usleep doesn't exist on win32, so we use Sleep() */
00082 #ifdef WIN32
00083 #define usleep(x) Sleep(x)
00084 #endif
00085 
00086 #ifdef HAVE_FCNTL_H
00087 
00096 int lock (int fd)
00097 {
00098     struct flock l;
00099     l.l_type = F_WRLCK; /*Do exclusive Lock*/
00100     l.l_start= 0;   /*Start at begin*/
00101     l.l_whence = SEEK_SET;
00102     l.l_len = 0;    /*Do it with whole file*/
00103     return fcntl (fd, F_SETLKW, &l);
00104 }
00105 
00106 
00116 int unlock (int fd)
00117 {
00118     struct flock l;
00119     l.l_type = F_UNLCK; /*Give Lock away*/
00120     l.l_start= 0;   /*Start at begin*/
00121     l.l_whence = SEEK_SET;
00122     l.l_len = 0;    /*Do it with whole file*/
00123     return fcntl (fd, F_SETLKW, &l);
00124 }
00125 #endif
00126 
00127 
00128 
00147 ssize_t unencode(char *encoded,void *returned) {
00148     char byteInHexa[5]="0x";
00149     char *readCursor=encoded;
00150     char *writeCursor=returned;
00151 
00152     if (!encoded) {
00153         if (returned) *(char *)returned=0;
00154         return 0;
00155     }
00156 
00157     byteInHexa[4]=0;
00158     while (*readCursor) {
00159         if (isspace((int)*readCursor)) 
00160         {
00161         readCursor++;
00162         continue;
00163         }
00164         if (isxdigit((int)*readCursor)) {
00165             long int converted;
00166             byteInHexa[2]=readCursor[0];
00167             byteInHexa[3]=readCursor[1];
00168             converted=strtol(byteInHexa,0,16); /* convert from hexa to a byte */
00169             *writeCursor=(unsigned char)converted;
00170 
00171             readCursor+=2;
00172             writeCursor++;
00173         } else {
00174             /* This is suposed to be a hex-digit stream. But is not, so return. */
00175             errno=KDB_RET_TYPEMISMATCH;
00176             return -1;
00177         }
00178     }
00179     return (long int)writeCursor-(long int)returned;
00180 }
00181 
00194 int kdbNeedsUTF8Conversion() {
00195 #if defined(HAVE_NL_LANGINFO) && defined(HAVE_ICONV) && defined(CODESET)
00196     return strcmp(nl_langinfo(CODESET),"UTF-8");
00197 #else
00198     return 0;
00199 #endif
00200 }
00201 
00202 
00228 int UTF8Engine(int direction, char **string, size_t *inputOutputByteSize) {
00229 /* Current solution is not very complete.
00230  * Iconv might well be available when a usable nl_langinfo is not.
00231  * In this case we it should be possible to determine charset through other means
00232  * See http://www.cl.cam.ac.uk/~mgk25/unicode.html#activate for more info on a possible solution */
00233  
00234 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) && defined(CODESET)
00235     char *currentCharset=0;
00236     char *converted=0;
00237     char *readCursor, *writeCursor;
00238     size_t bufferSize;
00239     iconv_t converter;
00240     
00241     if (kdbNeedsUTF8Conversion() && *inputOutputByteSize) currentCharset=nl_langinfo(CODESET);
00242     else return 0;
00243 
00244     if (direction==UTF8_TO) converter=iconv_open("UTF-8",currentCharset);
00245     else converter=iconv_open(currentCharset,"UTF-8");
00246 
00247     if (converter == (iconv_t)(-1)) return -1;
00248 
00249     /* work with worst case, when all chars are wide */
00250     bufferSize=*inputOutputByteSize * 4;
00251     converted=malloc(bufferSize);
00252     if (!converted) return -1;
00253 
00254     readCursor=*string;
00255     writeCursor=converted;
00256     /* On some systems and with libiconv, arg1 is const char **. 
00257      * ICONV_CONST is defined by configure if the system needs this */
00258     if (iconv(converter,
00259             (ICONV_CONST char **)&readCursor,inputOutputByteSize,
00260             &writeCursor,&bufferSize) == (size_t)(-1)) {
00261         free(converted);
00262         iconv_close(converter);
00263         return -1;
00264     }
00265 
00266     /* calculate the UTF-8 string byte size, that will be returned */
00267     *inputOutputByteSize=writeCursor-converted;
00268     /* store the current unencoded string for future free */
00269     readCursor=*string;
00270     /* allocate an optimal size area to store the converted string */
00271     *string=malloc(*inputOutputByteSize);
00272     /* copy all that matters for returning */
00273     memcpy(*string,converted,*inputOutputByteSize);
00274     /* release memory used by passed string */
00275     free(readCursor);
00276     /* release buffer memory */
00277     free(converted);
00278     /* release the conversor engine */
00279     iconv_close(converter);
00280 #endif
00281     return 0;
00282 }
00283 
00284 
00285 
00304 ssize_t encode(void *unencoded, size_t size, char *returned) {
00305     char *readCursor=unencoded;
00306     char *writeCursor=returned;
00307     int blockStep=4; /* 4 bytes per block */
00308     int lineStep=8*blockStep; /* 8 blocks per line */
00309     int currentInBlock=0;
00310     int currentInLine=0;
00311 
00312     if ( size == 0 )
00313         return 0;
00314     
00315     while ((readCursor-(char *)unencoded)<size) {
00316         sprintf(writeCursor,"%02x",*(unsigned char *)readCursor);
00317         readCursor++;
00318         writeCursor+=2;
00319         currentInBlock++;
00320         currentInLine++;
00321         if (currentInLine==lineStep) {
00322             *writeCursor='\n'; writeCursor++;
00323             currentInLine=0;
00324             currentInBlock=0;
00325         }
00326         if (currentInBlock==blockStep) {
00327             *writeCursor=' '; writeCursor++;
00328             currentInBlock=0;
00329         }
00330     }
00331     *writeCursor='\n';
00332     *++writeCursor=0;
00333     return writeCursor-returned;
00334 }
00335 
00336 
00348 int kdbRename_default(KDBHandle handle, Key *key, const char *newName)
00349 {
00350     Key *newKey;
00351 
00352     if ( (newKey = keyNew(KEY_SWITCH_END)) == NULL )
00353         return -1;
00354     
00355     if ( keyDup(key, newKey) ) {
00356         keyDel(newKey);
00357         return -1;
00358     }
00359     
00360     if ( keySetName(newKey, newName) ) {
00361         /* Create the new key */
00362         if ( kdbSetKey(handle, newKey) ) {
00363             keyDel(newKey);
00364             return -1;
00365         }
00366         keyDel(newKey);
00367         
00368         /* Remove the old one ... */
00369         if ( kdbRemoveKey(handle, key) ) 
00370             return -1;
00371 
00372         return 0;
00373     } else {
00374         /* newName isn't valid or empty */
00375         keyDel(newKey);
00376         return -1;  
00377     }
00378 }
00379 
00395 int kdbSetKeys_default(KDBHandle handle, KeySet *ks) {
00396     Key *current=ksCurrent(ks);
00397     int ret;
00398 
00399     if (!current) current=ksNext(ks);
00400     while (current) {
00401         if (keyNeedsSync(current))
00402             if ((ret=kdbSetKey(handle,current))) /* check error */
00403                 return ret;
00404         
00405         current=ksNext(ks);
00406     }
00407 
00408     return 0;
00409 }
00410 
00411 
00412 
00413 
00414 
00422 uint32_t kdbMonitorKey_default(KDBHandle handle, Key *interest,
00423         uint32_t diffMask, unsigned long iterations, unsigned sleeptime) {
00424     Key *tested;
00425     int rc;
00426     uint32_t diff;
00427     int infinitum=0;
00428 
00429     /* consistency */
00430     if (!interest || !keyGetNameSize(interest)) return 0;
00431 
00432     /* Unacceptable 0 usecs sleep. Defaults to 1 second */
00433     if (!sleeptime) sleeptime=1000;
00434 
00435     if (!iterations) infinitum=1;
00436     else infinitum=0;
00437 
00438     /* Work with a copy of the key */
00439     tested=keyNew(0);
00440     keyDup(interest,tested);
00441 
00442     while (infinitum || --iterations) {
00443         rc=kdbGetKey(handle,tested);
00444         if (rc) {
00445             /* check what type of problem happened.... */
00446             switch (errno) {
00447                 case KDB_RET_NOCRED:
00448                     keyDel(tested);
00449                     return KEY_SWITCH_NEEDSYNC;
00450                 case KDB_RET_NOTFOUND:
00451                     keyDel(tested);
00452                     return KEY_SWITCH_FLAG;
00453             }
00454         }
00455         
00456         diff=keyCompare(tested,interest);
00457         
00458         if (diff & diffMask) {
00459             /* If differences interests us, return it, otherwise cycle again.
00460              * We don't loose the original key context in a KeySet because
00461              * we worked with a copy of the key.
00462              */
00463             keyDup(tested,interest);
00464             keyDel(tested);
00465             return diff;
00466         }
00467         /* Test if some iterations left . . . */
00468         if (infinitum || iterations) usleep(sleeptime);
00469     }
00470     
00471     keyDel(tested);
00472 
00473     return 0;
00474 }
00475 

Generated on Tue Sep 11 10:38:50 2007 for Elektra Project by  doxygen 1.5.2