Back to index

courier  0.68.2
bdbobj.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2003 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 #if    HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 
00010 #include      <fcntl.h>
00011 #include      <string.h>
00012 #include      <stdlib.h>
00013 #if    HAVE_FCNTL_H
00014 #include      <fcntl.h>
00015 #endif
00016 #if    HAVE_UNISTD_H
00017 #include      <unistd.h>
00018 #endif
00019 
00020 #include      "bdbobj.h"
00021 
00022 void bdbobj_init(struct bdbobj *obj)
00023 {
00024        obj->has_dbf=0;
00025 
00026 #if    DB_VERSION_MAJOR >= 2
00027        obj->has_dbc=0;
00028 #endif
00029 }
00030 
00031 void bdbobj_close(struct bdbobj *obj)
00032 {
00033 #if    DB_VERSION_MAJOR >= 2
00034        if (obj->has_dbc)
00035        {
00036               (*obj->dbc->c_close)(obj->dbc);
00037               obj->has_dbc=0;
00038        }
00039 #endif
00040        if ( obj->has_dbf )
00041        {
00042 #if    DB_VERSION_MAJOR < 2
00043               (*obj->dbf->close)(obj->dbf);
00044 #else
00045               (*obj->dbf->close)(obj->dbf, 0);
00046 #endif
00047               obj->has_dbf=0;
00048        }
00049 }
00050 
00051 int bdbobj_open(struct bdbobj *obj, const char *filename, const char *modestr)
00052 {
00053 #if    DB_VERSION_MAJOR < 2
00054 
00055 int    flags=O_RDONLY;
00056 
00057 #else
00058 
00059 int    flags=DB_RDONLY;
00060 
00061 #endif
00062 
00063 DBTYPE dbtype=DB_HASH;
00064 
00065        for ( ; *modestr; modestr++)
00066               switch (*modestr)    {
00067               case 'c':
00068               case 'C':
00069 #if    DB_VERSION_MAJOR < 2
00070                      flags=O_RDWR|O_CREAT;
00071 #else
00072                      flags=DB_CREATE;
00073 #endif
00074                      break;
00075               case 'w':
00076               case 'W':
00077 #if    DB_VERSION_MAJOR < 2
00078                      flags=O_RDWR;
00079 #else
00080                      flags=0;
00081 #endif
00082                      break;
00083               case 'n':
00084               case 'N':
00085 #if    DB_VERSION_MAJOR < 2
00086                      flags=O_RDWR|O_CREAT|O_TRUNC;
00087 #else
00088                      flags=DB_CREATE|DB_TRUNCATE;
00089 #endif
00090 
00091                      break;
00092 
00093               case 'b':
00094               case 'B':
00095                      dbtype=DB_BTREE;
00096                      break;
00097 
00098               case 'e':
00099               case 'E':
00100                      dbtype=DB_RECNO;
00101                      break;
00102               }
00103 
00104        bdbobj_close(obj);
00105 
00106 #if DB_VERSION_MAJOR < 3
00107 #if DB_VERSION_MAJOR < 2
00108        if ( (obj->dbf=dbopen(filename, flags, 0664, dbtype, 0)) != 0)
00109 #else
00110        if ( db_open(filename, dbtype, flags, 0664, 0, 0, &obj->dbf) == 0)
00111 #endif
00112 #else
00113        obj->dbf=0;
00114 
00115 #define DB_40 0
00116 
00117 #if DB_VERSION_MAJOR == 4
00118 #if DB_VERSION_MINOR == 0
00119 
00120 #undef DB_40
00121 #define DB_40 1
00122 
00123 #endif
00124 #endif
00125 
00126 #if DB_VERSION_MAJOR == 3
00127 #undef DB_40
00128 #define DB_40 1
00129 #endif
00130 
00131        if (db_create(&obj->dbf, NULL, 0) == 0)
00132        {
00133               if ( (*obj->dbf->open)(obj->dbf,
00134 
00135 #if DB_40
00136 
00137 #else
00138                                    NULL,
00139 #endif
00140 
00141                                    filename, NULL,
00142                                    dbtype, flags, 0664))
00143               {
00144                      (*obj->dbf->close)(obj->dbf, DB_NOSYNC);
00145                      obj->dbf=0;
00146               }
00147        }
00148 
00149        if (obj->dbf)
00150 #endif
00151        {
00152 #ifdef  FD_CLOEXEC
00153 
00154 #if DB_VERSION_MAJOR < 2
00155         int     fd=(*obj->dbf->fd)(obj->dbf);
00156 #else
00157        int    fd;
00158 
00159               if ((*obj->dbf->fd)(obj->dbf, &fd))
00160                      fd= -1;
00161 #endif
00162 
00163                 if (fd >= 0)    fcntl(fd, F_SETFD, FD_CLOEXEC);
00164 #endif
00165 
00166 
00167               obj->has_dbf=1;
00168               return (0);
00169        }
00170        return (-1);
00171 }
00172 
00173 int bdbobj_store(struct bdbobj *obj, const char *key, size_t keylen,
00174               const char *data,
00175               size_t datalen,
00176               const  char *mode)
00177 {
00178 DBT dkey, dval;
00179 
00180        memset(&dkey, 0, sizeof(dkey));
00181        memset(&dval, 0, sizeof(dval));
00182 
00183        dkey.data=(void *)key;
00184        dkey.size=keylen;
00185        dval.data=(void *)data;
00186        dval.size=datalen;
00187 
00188 #if    DB_VERSION_MAJOR < 2
00189        return (obj->has_dbf ? (*obj->dbf->put)(obj->dbf, &dkey, &dval, (
00190                      *mode == 'i' || *mode == 'I' ?  R_NOOVERWRITE:0)):-1);
00191 #else
00192        return (obj->has_dbf ? (*obj->dbf->put)(obj->dbf, 0, &dkey, &dval, (
00193                      *mode == 'i' || *mode == 'I' ? DB_NOOVERWRITE:0)):-1);
00194 #endif
00195 }
00196 
00197 static char *doquery(struct bdbobj *obj,
00198        const char *, size_t, size_t *, const char *);
00199 
00200 char   *bdbobj_fetch(struct bdbobj *obj, const char *key, size_t keylen,
00201               size_t *datalen, const char *options)
00202 {
00203 char   *p=doquery(obj, key, keylen, datalen, options);
00204 char   *q;
00205 
00206        if (!p)       return (0);
00207 
00208        q=(char *)malloc(*datalen);
00209 
00210        if (!q)       return (0);
00211 
00212        memcpy(q, p, *datalen);
00213        return (q);
00214 }
00215 
00216 char    *dofetch(struct bdbobj *, const char *, size_t, size_t *);
00217 
00218 static char *doquery(struct bdbobj *obj, const char *key, size_t keylen,
00219        size_t *datalen, const char *options)
00220 {
00221 char   *p;
00222 
00223        for (;;)
00224        {
00225               if ((p=dofetch(obj, key, keylen, datalen)) != 0)
00226                      return (p);
00227               if (!options) break;
00228               if (*options == 'I')
00229               {
00230                      while (keylen && key[--keylen] != '.')
00231                             ;
00232                      if (!keylen)  break;
00233                      continue;
00234               }
00235               if (*options == 'D')
00236               {
00237               size_t i;
00238 
00239                      for (i=0; i<keylen; i++)
00240                             if (key[i] == '@') { ++i; break; }
00241                      if (i < keylen)
00242                      {
00243                             if ((p=dofetch(obj, key, i, datalen)) != 0)
00244                                    return (p);
00245                             key += i;
00246                             keylen -= i;
00247                             continue;
00248                      }
00249 
00250                      for (i=0; i<keylen; i++)
00251                             if (key[i] == '.') { ++i; break; }
00252                      if (i < keylen)
00253                      {
00254                             key += i;
00255                             keylen -= i;
00256                             continue;
00257                      }
00258                      break;
00259               }
00260               break;
00261        }
00262        return (0);
00263 }
00264 
00265 char   *dofetch(struct bdbobj *obj, const char *key, size_t keylen,
00266        size_t *datalen)
00267 {
00268 DBT    dkey, val;
00269 
00270        if (!obj->has_dbf)   return (0);
00271 
00272        memset(&dkey, 0, sizeof(dkey));
00273        memset(&val, 0, sizeof(val));
00274 
00275        dkey.data=(void *)key;
00276        dkey.size=keylen;
00277 
00278 #if    DB_VERSION_MAJOR < 2
00279        if ( (*obj->dbf->get)(obj->dbf, &dkey, &val, 0)) return (0);
00280 #else
00281        if ( (*obj->dbf->get)(obj->dbf, 0, &dkey, &val, 0)) return (0);
00282 #endif
00283 
00284        *datalen=val.size;
00285        return ((char *)val.data);
00286 }
00287 
00288 int    bdbobj_exists(struct bdbobj *obj, const char *key, size_t keylen)
00289 {
00290 size_t datalen;
00291 char   *p=doquery(obj, key, keylen, &datalen, 0);
00292 
00293        return (p ? 1:0);
00294 }