Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions | Variables
dbmshim.c File Reference
#include "mcom_db.h"
#include "secitem.h"
#include "secder.h"
#include "prprf.h"
#include "cdbhdl.h"
#include "pcertt.h"
#include "secasn1.h"
#include "secerr.h"
#include "nssb64.h"
#include "blapi.h"
#include "sechash.h"
#include "pkcs11i.h"

Go to the source code of this file.

Classes

struct  DBSStr

Defines

#define DBS_BLOCK_SIZE   (16*1024) /* 16 k */
#define DBS_MAX_ENTRY_SIZE   (DBS_BLOCK_SIZE - (2048)) /* 14 k */
#define DBS_CACHE_SIZE   DBS_BLOCK_SIZE*8
#define ROUNDDIV(x, y)   (x+(y-1))/y
#define BLOB_HEAD_LEN   4
#define BLOB_LENGTH_START   BLOB_HEAD_LEN
#define BLOB_LENGTH_LEN   4
#define BLOB_NAME_START   BLOB_LENGTH_START+BLOB_LENGTH_LEN
#define BLOB_NAME_LEN   1+ROUNDDIV(SHA1_LENGTH,3)*4+1
#define BLOB_BUF_LEN   BLOB_HEAD_LEN+BLOB_LENGTH_LEN+BLOB_NAME_LEN
#define DIRSUFFIX   ".dir"
#define DBM_DEFAULT   0

Typedefs

typedef struct DBSStr

Functions

static PRBool dbs_IsBlob (DBT *blobData)
static const char * dbs_getBlobFileName (DBT *blobData)
static PRUint32 dbs_getBlobSize (DBT *blobData)
static void dbs_replaceSlash (char *cp, int len)
static void dbs_mkBlob (DBS *dbsp, const DBT *key, const DBT *data, DBT *blobData)
static char * dbs_getBlobFilePath (char *blobdir, DBT *blobData)
static void dbs_removeBlob (DBS *dbsp, DBT *blobData)
static int dbs_DirMode (int mode)
static int dbs_writeBlob (DBS *dbsp, int mode, DBT *blobData, const DBT *data)
static void dbs_freemap (DBS *dbsp)
static void dbs_setmap (DBS *dbsp, PRFileMap *mapfile, unsigned char *addr, PRUint32 len)
static unsigned char * dbs_EmulateMap (PRFileDesc *filed, int len)
static int dbs_readBlob (DBS *dbsp, DBT *data)
static int dbs_get (const DB *dbs, const DBT *key, DBT *data, unsigned int flags)
static int dbs_put (const DB *dbs, DBT *key, const DBT *data, unsigned int flags)
static int dbs_sync (const DB *dbs, unsigned int flags)
static int dbs_del (const DB *dbs, const DBT *key, unsigned int flags)
static int dbs_seq (const DB *dbs, DBT *key, DBT *data, unsigned int flags)
static int dbs_close (DB *dbs)
static int dbs_fd (const DB *dbs)
static char * dbs_mkBlobDirName (const char *dbname)
DBdbsopen (const char *dbname, int flags, int mode, DBTYPE type, const void *userData)

Variables

static const HASHINFO dbs_hashInfo

Class Documentation

struct DBSStr

Definition at line 88 of file dbmshim.c.

Collaboration diagram for DBSStr:
Class Members
char * blobdir
DB db
unsigned char * dbs_addr
PRUint32 dbs_len
PRFileMap * dbs_mapfile
int mode
PRBool readOnly
char staticBlobArea

Define Documentation

Definition at line 83 of file dbmshim.c.

Definition at line 78 of file dbmshim.c.

Definition at line 80 of file dbmshim.c.

Definition at line 79 of file dbmshim.c.

Definition at line 82 of file dbmshim.c.

Definition at line 81 of file dbmshim.c.

Definition at line 587 of file dbmshim.c.

#define DBS_BLOCK_SIZE   (16*1024) /* 16 k */

Definition at line 74 of file dbmshim.c.

Definition at line 76 of file dbmshim.c.

#define DBS_MAX_ENTRY_SIZE   (DBS_BLOCK_SIZE - (2048)) /* 14 k */

Definition at line 75 of file dbmshim.c.

#define DIRSUFFIX   ".dir"

Definition at line 555 of file dbmshim.c.

#define ROUNDDIV (   x,
  y 
)    (x+(y-1))/y

Definition at line 77 of file dbmshim.c.


Typedef Documentation

typedef struct DBSStr

Definition at line 86 of file dbmshim.c.


Function Documentation

static int dbs_close ( DB dbs) [static]

Definition at line 528 of file dbmshim.c.

{
    DBS *dbsp = (DBS *)dbs;
    DB *db = (DB *)dbs->internal;
    int ret;

    dbs_freemap(dbsp);
    ret = (* db->close)(db);
    PORT_Free(dbsp->blobdir);
    PORT_Free(dbsp);
    return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dbs_del ( const DB dbs,
const DBT key,
unsigned int  flags 
) [static]

Definition at line 490 of file dbmshim.c.

{
    int ret;
    DBS *dbsp = (DBS *)dbs;
    DB *db = (DB *)dbs->internal;

    dbs_freemap(dbsp);

    if (!dbsp->readOnly) {
       DBT oldData;
       ret = (*db->get)(db,key,&oldData,0);
       if ((ret == 0) && dbs_IsBlob(&oldData)) {
           dbs_removeBlob(dbsp,&oldData);
       }
    }

    return (* db->del)(db, key, flags);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dbs_DirMode ( int  mode) [static]

Definition at line 239 of file dbmshim.c.

{
  int x_bits = (mode >> 2) &  0111;
  return mode | x_bits;
}

Here is the caller graph for this function:

static unsigned char* dbs_EmulateMap ( PRFileDesc filed,
int  len 
) [static]

Definition at line 334 of file dbmshim.c.

{
    unsigned char *addr;
    PRInt32 dataRead;

    addr = PORT_Alloc(len);
    if (addr == NULL) {
       return NULL;
    }

    dataRead = PR_Read(filed,addr,len);
    if (dataRead != len) {
       PORT_Free(addr);
       if (dataRead > 0) {
           /* PR_Read didn't set an error, we need to */
           PR_SetError(SEC_ERROR_BAD_DATABASE,0);
       }
       return NULL;
    }

    return addr;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dbs_fd ( const DB dbs) [static]

Definition at line 542 of file dbmshim.c.

{
    DB *db = (DB *)dbs->internal;

    return (* db->fd)(db);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dbs_freemap ( DBS *  dbsp) [static]

Definition at line 306 of file dbmshim.c.

{
    if (dbsp->dbs_mapfile) {
       PR_MemUnmap(dbsp->dbs_addr,dbsp->dbs_len);
       PR_CloseFileMap(dbsp->dbs_mapfile);
       dbsp->dbs_mapfile = NULL;
       dbsp->dbs_addr = NULL;
       dbsp->dbs_len = 0;
    } else if (dbsp->dbs_addr) {
       PORT_Free(dbsp->dbs_addr);
       dbsp->dbs_addr = NULL;
       dbsp->dbs_len = 0;
    }
    return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dbs_get ( const DB dbs,
const DBT key,
DBT data,
unsigned int  flags 
) [static]

Definition at line 423 of file dbmshim.c.

{
    int ret;
    DBS *dbsp = (DBS *)dbs;
    DB *db = (DB *)dbs->internal;
    

    dbs_freemap(dbsp);
    
    ret = (* db->get)(db, key, data, flags);
    if ((ret == 0) && dbs_IsBlob(data)) {
       ret = dbs_readBlob(dbsp,data);
    }

    return(ret);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* dbs_getBlobFileName ( DBT blobData) [static]

Definition at line 119 of file dbmshim.c.

{
    char *addr = (char *)blobData->data;

    return &addr[BLOB_NAME_START];
}

Here is the caller graph for this function:

static char* dbs_getBlobFilePath ( char *  blobdir,
DBT blobData 
) [static]

Definition at line 198 of file dbmshim.c.

{
    const char *name;

    if (blobdir == NULL) {
       PR_SetError(SEC_ERROR_BAD_DATABASE,0);
       return NULL;
    }
    if (!dbs_IsBlob(blobData)) {
       PR_SetError(SEC_ERROR_BAD_DATABASE,0);
       return NULL;
    }
    name = dbs_getBlobFileName(blobData);
    if (!name || *name == 0) {
       PR_SetError(SEC_ERROR_BAD_DATABASE,0);
       return NULL;
    }
    return  PR_smprintf("%s" PATH_SEPARATOR "%s", blobdir, name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRUint32 dbs_getBlobSize ( DBT blobData) [static]

Definition at line 130 of file dbmshim.c.

{
    unsigned char *addr = (unsigned char *)blobData->data;

    return (PRUint32)(addr[BLOB_LENGTH_START+3] << 24) | 
                     (addr[BLOB_LENGTH_START+2] << 16) | 
                     (addr[BLOB_LENGTH_START+1] << 8) | 
                     addr[BLOB_LENGTH_START];
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool dbs_IsBlob ( DBT blobData) [static]

Definition at line 105 of file dbmshim.c.

{
    unsigned char *addr = (unsigned char *)blobData->data;
    if (blobData->size < BLOB_BUF_LEN) {
       return PR_FALSE;
    }
    return addr && ((certDBEntryType) addr[1] == certDBEntryTypeBlob);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dbs_mkBlob ( DBS *  dbsp,
const DBT key,
const DBT data,
DBT blobData 
) [static]

Definition at line 161 of file dbmshim.c.

{
   unsigned char sha1_data[SHA1_LENGTH];
   char *b = dbsp->staticBlobArea;
   PRUint32 length = data->size;
   SECItem sha1Item;

   b[0] = CERT_DB_FILE_VERSION; /* certdb version number */
   b[1] = (char) certDBEntryTypeBlob; /* type */
   b[2] = 0; /* flags */
   b[3] = 0; /* reserved */
   b[BLOB_LENGTH_START] = length & 0xff;
   b[BLOB_LENGTH_START+1] = (length >> 8) & 0xff;
   b[BLOB_LENGTH_START+2] = (length >> 16) & 0xff;
   b[BLOB_LENGTH_START+3] = (length >> 24) & 0xff;
   sha1Item.data = sha1_data;
   sha1Item.len = SHA1_LENGTH;
   SHA1_HashBuf(sha1_data,key->data,key->size);
   b[BLOB_NAME_START]='b'; /* Make sure we start with a alpha */
   NSSBase64_EncodeItem(NULL,&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1,&sha1Item);
   b[BLOB_BUF_LEN-1] = 0;
   dbs_replaceSlash(&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1);
   blobData->data = b;
   blobData->size = BLOB_BUF_LEN;
   return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* dbs_mkBlobDirName ( const char *  dbname) [static]

Definition at line 557 of file dbmshim.c.

{
    int dbname_len = PORT_Strlen(dbname);
    int dbname_end = dbname_len;
    const char *cp;
    char *blobDir = NULL;

    /* scan back from the end looking for either a directory separator, a '.',
     * or the end of the string. NOTE: Windows should check for both separators
     * here. For now this is safe because we know NSS always uses a '.'
     */
    for (cp = &dbname[dbname_len]; 
              (cp > dbname) && (*cp != '.') && (*cp != *PATH_SEPARATOR) ;
                     cp--)
       /* Empty */ ;
    if (*cp == '.') {
       dbname_end = cp - dbname;
       if (PORT_Strcmp(cp,DIRSUFFIX) == 0) {
           dbname_end = dbname_len;
       }
    }
    blobDir = PORT_ZAlloc(dbname_end+sizeof(DIRSUFFIX));
    if (blobDir == NULL) {
       return NULL;
    }
    PORT_Memcpy(blobDir,dbname,dbname_end);
    PORT_Memcpy(&blobDir[dbname_end],DIRSUFFIX,sizeof(DIRSUFFIX));
    return blobDir;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dbs_put ( const DB dbs,
DBT key,
const DBT data,
unsigned int  flags 
) [static]

Definition at line 441 of file dbmshim.c.

{
    DBT blob;
    int ret = 0;
    DBS *dbsp = (DBS *)dbs;
    DB *db = (DB *)dbs->internal;

    dbs_freemap(dbsp);

    /* If the db is readonly, just pass the data down to rdb and let it fail */
    if (!dbsp->readOnly) {
       DBT oldData;
       int ret1;

       /* make sure the current record is deleted if it's a blob */
       ret1 = (*db->get)(db,key,&oldData,0);
        if ((ret1 == 0) && flags == R_NOOVERWRITE) {
           /* let DBM return the error to maintain consistancy */
           return (* db->put)(db, key, data, flags);
       }
       if ((ret1 == 0) && dbs_IsBlob(&oldData)) {
           dbs_removeBlob(dbsp, &oldData);
       }

       if (data->size > DBS_MAX_ENTRY_SIZE) {
           dbs_mkBlob(dbsp,key,data,&blob);
           ret = dbs_writeBlob(dbsp, dbsp->mode, &blob, data);
           data = &blob;
       }
    }

    if (ret == 0) {
       ret = (* db->put)(db, key, data, flags);
    }
    return(ret);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dbs_readBlob ( DBS *  dbsp,
DBT data 
) [static]

Definition at line 364 of file dbmshim.c.

{
    char *file = NULL;
    PRFileDesc *filed = NULL;
    PRFileMap *mapfile = NULL;
    unsigned char *addr = NULL;
    int error;
    int len = -1;

    file = dbs_getBlobFilePath(dbsp->blobdir, data);
    if (!file) {
       goto loser;
    }
    filed = PR_OpenFile(file,PR_RDONLY,0);
    PR_smprintf_free(file); file = NULL;
    if (filed == NULL) {
       goto loser;
    }

    len = dbs_getBlobSize(data);
    mapfile = PR_CreateFileMap(filed, len, PR_PROT_READONLY);
    if (mapfile == NULL) {
        /* USE PR_GetError instead of PORT_GetError here
         * because we are getting the error from PR_xxx
         * function */
       if (PR_GetError() != PR_NOT_IMPLEMENTED_ERROR) {
           goto loser;
       }
       addr = dbs_EmulateMap(filed, len);
    } else {
       addr = PR_MemMap(mapfile, 0, len);
    }
    if (addr == NULL) {
       goto loser;
    }
    PR_Close(filed);
    dbs_setmap(dbsp,mapfile,addr,len);

    data->data = addr;
    data->size = len;
    return 0;

loser:
    /* preserve the error code */
    error = PR_GetError();
    if (mapfile) {
       PR_CloseFileMap(mapfile);
    }
    if (filed) {
       PR_Close(filed);
    }
    PR_SetError(error,0);
    return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dbs_removeBlob ( DBS *  dbsp,
DBT blobData 
) [static]

Definition at line 222 of file dbmshim.c.

{
    char *file;

    file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
    if (!file) {
       return;
    }
    PR_Delete(file);
    PR_smprintf_free(file);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dbs_replaceSlash ( char *  cp,
int  len 
) [static]

Definition at line 148 of file dbmshim.c.

{
   while (len--) {
       if (*cp == '/') *cp = '-';
       cp++;
   }
}

Here is the caller graph for this function:

static int dbs_seq ( const DB dbs,
DBT key,
DBT data,
unsigned int  flags 
) [static]

Definition at line 510 of file dbmshim.c.

{
    int ret;
    DBS *dbsp = (DBS *)dbs;
    DB *db = (DB *)dbs->internal;
    
    dbs_freemap(dbsp);
    
    ret = (* db->seq)(db, key, data, flags);
    if ((ret == 0) && dbs_IsBlob(data)) {
       /* don't return a blob read as an error so traversals keep going */
       (void) dbs_readBlob(dbsp,data);
    }

    return(ret);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dbs_setmap ( DBS *  dbsp,
PRFileMap mapfile,
unsigned char *  addr,
PRUint32  len 
) [static]

Definition at line 323 of file dbmshim.c.

{
    dbsp->dbs_mapfile = mapfile;
    dbsp->dbs_addr = addr;
    dbsp->dbs_len = len;
}

Here is the caller graph for this function:

static int dbs_sync ( const DB dbs,
unsigned int  flags 
) [static]

Definition at line 479 of file dbmshim.c.

{
    DB *db = (DB *)dbs->internal;
    DBS *dbsp = (DBS *)dbs;

    dbs_freemap(dbsp);

    return (* db->sync)(db, flags);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dbs_writeBlob ( DBS *  dbsp,
int  mode,
DBT blobData,
const DBT data 
) [static]

Definition at line 250 of file dbmshim.c.

{
    char *file = NULL;
    PRFileDesc *filed;
    PRStatus status;
    int len;
    int error = 0;

    file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
    if (!file) {
       goto loser;
    }
    if (PR_Access(dbsp->blobdir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
       status = PR_MkDir(dbsp->blobdir,dbs_DirMode(mode));
       if (status != PR_SUCCESS) {
           goto loser;
       }
    }
    filed = PR_OpenFile(file,PR_CREATE_FILE|PR_TRUNCATE|PR_WRONLY, mode);
    if (filed == NULL) {
       error = PR_GetError();
       goto loser;
    }
    len = PR_Write(filed,data->data,data->size);
    error = PR_GetError();
    PR_Close(filed);
    if (len < (int)data->size) {
       goto loser;
    }
    PR_smprintf_free(file);
    return 0;

loser:
    if (file) {
       PR_Delete(file);
       PR_smprintf_free(file);
    }
    /* don't let close or delete reset the error */
    PR_SetError(error,0);
    return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

DB* dbsopen ( const char *  dbname,
int  flags,
int  mode,
DBTYPE  type,
const void userData 
)

Definition at line 604 of file dbmshim.c.

{
    DB *db = NULL,*dbs = NULL;
    DBS *dbsp = NULL;

    /* NOTE: we are overriding userData with dbs_hashInfo. since all known
     * callers pass 0, this is ok, otherwise we should merge the two */

    dbsp = (DBS *)PORT_ZAlloc(sizeof(DBS));
    if (!dbsp) {
       return NULL;
    }
    dbs = &dbsp->db;

    dbsp->blobdir=dbs_mkBlobDirName(dbname);
    if (dbsp->blobdir == NULL) {
       goto loser;
    }
    dbsp->mode = mode;
    dbsp->readOnly = (PRBool)(flags == NO_RDONLY);
    dbsp->dbs_mapfile = NULL;
    dbsp->dbs_addr = NULL;
    dbsp->dbs_len = 0;

    /* the real dbm call */
    db = dbopen(dbname, flags, mode, type, &dbs_hashInfo);
    if (db == NULL) {
       goto loser;
    }
    dbs->internal = (void *) db;
    dbs->type = type;
    dbs->close = dbs_close;
    dbs->get = dbs_get;
    dbs->del = dbs_del;
    dbs->put = dbs_put;
    dbs->seq = dbs_seq;
    dbs->sync = dbs_sync;
    dbs->fd = dbs_fd;

    return dbs;
loser:
    if (db) {
       (*db->close)(db);
    }
    if (dbsp && dbsp->blobdir) {
       PORT_Free(dbsp->blobdir);
    }
    if (dbsp) {
       PORT_Free(dbsp);
    }
    return NULL;
}

Variable Documentation

Initial value:

Definition at line 588 of file dbmshim.c.