/* get the next key */ datum dbm_nextkey(DBM *db){ struct stat statb; datum item; if(dbm_error(db) || fstat(db->dbm_pagf, &statb) < 0) goto err; statb.st_size /= PBLKSIZ; for(;;){ if(db->dbm_blkptr != db->dbm_pagbno){ db->dbm_pagbno = db->dbm_blkptr; (void) lseek(db->dbm_pagf, db->dbm_blkptr*PBLKSIZ, SEEK_SET); if(read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) memset(db->dbm_pagbuf, 0, PBLKSIZ); } if(((short *)db->dbm_pagbuf)[0] != 0){ item = makdatum(db->dbm_pagbuf, db->dbm_keyptr); if(item.dptr != NULL){ db->dbm_keyptr += 2; return (item); } db->dbm_keyptr = 0; } if(++db->dbm_blkptr >= statb.st_size) break; } err: item.dptr = NULL; item.dsize = 0; return (item); }
int dbm_delete(DBM *db, datum key) { int i; if (dbm_error(db)) return (-1); if (dbm_rdonly(db)) { errno = EPERM; return (-1); } dbm_access(db, dcalchash(key)); if ((i = finddatum(db->dbm_pagbuf, key)) < 0) return (-1); if (!delitem(db->dbm_pagbuf, i)) goto err; db->dbm_pagbno = db->dbm_blkno; if (dbm_defwrite(db)) { dbm_setdirty(db); } else { (void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET); if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { err: db->dbm_flags |= _DBM_IOERR; return (-1); } } return (0); }
int ldbm_errno( LDBM ldbm ) { int err; LDBM_WLOCK; err = dbm_error( ldbm ); LDBM_WUNLOCK; return err; }
/* retrieve a record */ datum dbm_fetch(DBM *db, datum key){ int i; datum item; if(dbm_error(db)) goto err; dbm_access(db, dcalchash(key)); if((i = finddatum(db->dbm_pagbuf, key)) >= 0){ item = makdatum(db->dbm_pagbuf, i+1); if(item.dptr != NULL) return (item); } err: item.dptr = NULL; item.dsize = 0; return (item); }
static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said) { apr_status_t rv = APR_SUCCESS; /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */ dbm->errmsg = NULL; if (dbm_error((DBM*)dbm->file)) { dbm->errmsg = NULL; rv = APR_EGENERAL; /* ### need something better */ } /* captured it. clear it now. */ dbm_clearerr((DBM*)dbm->file); return rv; }
static int dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w) { datum krec, drec; int tmp_size; if ( !PyArg_Parse(v, "s#", &krec.dptr, &tmp_size) ) { PyErr_SetString(PyExc_TypeError, "dbm mappings have string indices only"); return -1; } krec.dsize = tmp_size; if (dp->di_dbm == NULL) { PyErr_SetString(DbmError, "DBM object has already been closed"); return -1; } dp->di_size = -1; if (w == NULL) { if ( dbm_delete(dp->di_dbm, krec) < 0 ) { dbm_clearerr(dp->di_dbm); PyErr_SetString(PyExc_KeyError, PyString_AS_STRING((PyStringObject *)v)); return -1; } } else { if ( !PyArg_Parse(w, "s#", &drec.dptr, &tmp_size) ) { PyErr_SetString(PyExc_TypeError, "dbm mappings have string elements only"); return -1; } drec.dsize = tmp_size; if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) { dbm_clearerr(dp->di_dbm); PyErr_SetString(DbmError, "cannot add item to database"); return -1; } } if ( dbm_error(dp->di_dbm) ) { dbm_clearerr(dp->di_dbm); PyErr_SetString(DbmError, ""); return -1; } return 0; }
static datum dbm_slow_nextkey(DBM *db) { struct stat statb; datum item; if (dbm_error(db) || fstat(db->dbm_pagf, &statb) < 0) goto err; statb.st_size /= PBLKSIZ; for (;;) { if (db->dbm_blkptr != db->dbm_pagbno) { if (dbm_dirty(db)) dbm_flushpag(db); db->dbm_pagbno = db->dbm_blkptr; (void) lseek(db->dbm_pagf, (long)(db->dbm_blkptr*PBLKSIZ), L_SET); if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) bzero(db->dbm_pagbuf, PBLKSIZ); #ifdef DEBUG else if (chkblk(db->dbm_pagbuf) < 0) db->dbm_flags |= _DBM_IOERR; #endif } /*Am I an empty block?*/ if (((short *)db->dbm_pagbuf)[0] != 0) { item = makdatum(db->dbm_pagbuf, db->dbm_keyptr); if (item.dptr != NULL) { db->dbm_keyptr += 2; return (item); } db->dbm_keyptr = 0; } /*go to next sequential block*/ if (++db->dbm_blkptr >= statb.st_size) break; } err: item.dptr = NULL; item.dsize = 0; return (item); }
static PyObject * dbm_subscript(dbmobject *dp, PyObject *key) { datum drec, krec; Py_ssize_t tmp_size; if (!PyArg_Parse(key, "s#", &krec.dptr, &tmp_size) ) return NULL; krec.dsize = tmp_size; check_dbmobject_open(dp); drec = dbm_fetch(dp->di_dbm, krec); if ( drec.dptr == 0 ) { PyErr_SetObject(PyExc_KeyError, key); return NULL; } if ( dbm_error(dp->di_dbm) ) { dbm_clearerr(dp->di_dbm); PyErr_SetString(DbmError, ""); return NULL; } return PyBytes_FromStringAndSize(drec.dptr, drec.dsize); }
/* store a record */ int dbm_store(DBM *db, datum key, datum dat, int replace){ int i; datum item, item1; char ovfbuf[PBLKSIZ]; if(dbm_error(db)) return (-1); if(dbm_rdonly(db)){ errno = EPERM; return (-1); } loop: dbm_access(db, dcalchash(key)); if((i = finddatum(db->dbm_pagbuf, key)) >= 0){ if(!replace) return (1); if(!delitem(db->dbm_pagbuf, i)){ db->dbm_flags |= _DBM_IOERR; return (-1); } } if(!additem(db->dbm_pagbuf, key, dat)) goto split; db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, SEEK_SET); if(write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ){ db->dbm_flags |= _DBM_IOERR; return (-1); } return (0); split: if(key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ){ db->dbm_flags |= _DBM_IOERR; errno = ENOSPC; return (-1); } memset(ovfbuf, 0, PBLKSIZ); for(i=0;;){ item = makdatum(db->dbm_pagbuf, i); if(item.dptr == NULL) break; if(dcalchash(item) & (db->dbm_hmask+1)){ item1 = makdatum(db->dbm_pagbuf, i+1); if(item1.dptr == NULL){ db->dbm_flags |= _DBM_IOERR; break; } if(!additem(ovfbuf, item, item1) || !delitem(db->dbm_pagbuf, i)){ db->dbm_flags |= _DBM_IOERR; return (-1); } continue; } i += 2; } db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, SEEK_SET); if(write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ){ db->dbm_flags |= _DBM_IOERR; return (-1); } (void) lseek(db->dbm_pagf, (db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ, SEEK_SET); if(write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ){ db->dbm_flags |= _DBM_IOERR; return (-1); } setbit(db); goto loop; }
int main(int argc, char **argv) { typedef enum { YOW, FETCH, STORE, DELETE, SCAN, REGEXP } commands; char opt; int flags; int giveusage = 0; int verbose = 0; commands what = YOW; char *comarg[3]; int st_flag = DBM_INSERT; int argn; DBM *db; datum key; datum content; flags = O_RDWR; argn = 0; while ((opt = getopt(argc, argv, "acdfFm:rstvx")) != ':') { switch (opt) { case 'a': what = SCAN; break; case 'c': flags |= O_CREAT; break; case 'd': what = DELETE; break; case 'f': what = FETCH; break; case 'F': what = REGEXP; break; case 'm': flags &= ~(000007); if (strcmp(optarg, "r") == 0) flags |= O_RDONLY; else if (strcmp(optarg, "w") == 0) flags |= O_WRONLY; else if (strcmp(optarg, "rw") == 0) flags |= O_RDWR; else { fprintf(stderr, "Invalid mode: \"%s\"\n", optarg); giveusage = 1; } break; case 'r': st_flag = DBM_REPLACE; break; case 's': what = STORE; break; case 't': flags |= O_TRUNC; break; case 'v': verbose = 1; break; case 'x': flags |= O_EXCL; break; case '!': giveusage = 1; break; case '?': if (argn < 3) comarg[argn++] = optarg; else { fprintf(stderr, "Too many arguments.\n"); giveusage = 1; } break; } } if (giveusage || what == YOW || argn < 1) { fprintf(stderr, "Usage: %s database [-m r|w|rw] [-crtx] -a|-d|-f|-F|-s [key [content]]\n", argv[0]); exit(-1); } if ((db = dbm_open(comarg[0], flags, 0777)) == NULL) { fprintf(stderr, "Error opening database \"%s\"\n", comarg[0]); exit(-1); } if (argn > 1) key = read_datum(comarg[1]); if (argn > 2) content = read_datum(comarg[2]); switch (what) { case SCAN: key = dbm_firstkey(db); if (dbm_error(db)) { fprintf(stderr, "Error when fetching first key\n"); goto db_exit; } while (key.dptr != NULL) { content = dbm_fetch(db, key); if (dbm_error(db)) { fprintf(stderr, "Error when fetching "); print_datum(key); printf("\n"); goto db_exit; } print_datum(key); printf(": "); print_datum(content); printf("\n"); if (dbm_error(db)) { fprintf(stderr, "Error when fetching next key\n"); goto db_exit; } key = dbm_nextkey(db); } break; case REGEXP: if (argn < 2) { fprintf(stderr, "Missing regular expression.\n"); goto db_exit; } if (re_comp(comarg[1])) { fprintf(stderr, "Invalid regular expression\n"); goto db_exit; } key = dbm_firstkey(db); if (dbm_error(db)) { fprintf(stderr, "Error when fetching first key\n"); goto db_exit; } while (key.dptr != NULL) { if (re_exec(key2s(key))) { content = dbm_fetch(db, key); if (dbm_error(db)) { fprintf(stderr, "Error when fetching "); print_datum(key); printf("\n"); goto db_exit; } print_datum(key); printf(": "); print_datum(content); printf("\n"); if (dbm_error(db)) { fprintf(stderr, "Error when fetching next key\n"); goto db_exit; } } key = dbm_nextkey(db); } break; case FETCH: if (argn < 2) { fprintf(stderr, "Missing fetch key.\n"); goto db_exit; } content = dbm_fetch(db, key); if (dbm_error(db)) { fprintf(stderr, "Error when fetching "); print_datum(key); printf("\n"); goto db_exit; } if (content.dptr == NULL) { fprintf(stderr, "Cannot find "); print_datum(key); printf("\n"); goto db_exit; } print_datum(key); printf(": "); print_datum(content); printf("\n"); break; case DELETE: if (argn < 2) { fprintf(stderr, "Missing delete key.\n"); goto db_exit; } if (dbm_delete(db, key) || dbm_error(db)) { fprintf(stderr, "Error when deleting "); print_datum(key); printf("\n"); goto db_exit; } if (verbose) { print_datum(key); printf(": DELETED\n"); } break; case STORE: if (argn < 3) { fprintf(stderr, "Missing key and/or content.\n"); goto db_exit; } if (dbm_store(db, key, content, st_flag) || dbm_error(db)) { fprintf(stderr, "Error when storing "); print_datum(key); printf("\n"); goto db_exit; } if (verbose) { print_datum(key); printf(": "); print_datum(content); printf(" STORED\n"); } break; } db_exit: dbm_clearerr(db); dbm_close(db); if (dbm_error(db)) { fprintf(stderr, "Error closing database \"%s\"\n", comarg[0]); exit(-1); } }
datum dbm_do_nextkey(DBM *db, datum inkey) { datum item,bitem; long hash; datum key; int f; int i; int j; short *sp; int n; char *p1, *p2; if ( dbm_error(db) ) { item.dptr = NULL; item.dsize = 0; return (item); } /*user has supplied lastkey*/ if(inkey.dptr != NULL) { dbm_access(db, (hash=dcalchash(inkey))); if ((i = finddatum(db->dbm_pagbuf, inkey)) >= 0) { db->dbm_keyptr = i + 2; db->dbm_blkptr = db->dbm_blkno; } key=inkey; } else { /*is this a manual firstkey request? */ if (db->dbm_blkptr == 0L && db->dbm_keyptr == 0) return (dbm_firsthash(db, 0L)); /*no -- get lastkey this is like dbm_access by blkptr*/ if (db->dbm_blkptr != db->dbm_pagbno) { if (dbm_dirty(db)) dbm_flushpag(db); db->dbm_pagbno = db->dbm_blkptr; (void) lseek(db->dbm_pagf, (long)(db->dbm_blkptr*PBLKSIZ), L_SET); if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) bzero(db->dbm_pagbuf, PBLKSIZ); #ifdef DEBUG else if (chkblk(db->dbm_pagbuf) < 0) db->dbm_flags |= _DBM_IOERR; #endif } /*now just make up last key datum*/ if (db->dbm_keyptr >=2) key= makdatum(db->dbm_pagbuf,(db->dbm_keyptr-2)); else key=nullkey; /* the keyptr pagbuf have failed us, the user must be an extra clever moron who depends on these variables and their former meaning. If we set the variables this would have got us the key for sure! So give him the old algorithm.*/ if (key.dptr == NULL) return (dbm_slow_nextkey(db)); } /*at this point the last key is paged in and we can proceed as in old dbm -- like Ken did his. */ f = 1; j=0; sp = (short *)db->dbm_pagbuf; for(i=0;; i+=2) { /*begin put makdatum inline*/ if ((unsigned)i >= sp[0]) { item.dptr = NULL; item.dsize = 0; break; /*from below*/ } else { if (i > 0) item.dsize = sp[i] - sp[i+1]; else item.dsize = PBLKSIZ - sp[i+1]; item.dptr = db->dbm_pagbuf+sp[i+1]; } /* item = makdatum(db->dbm_pagbuf, i);*/ /*end put makdatum inline*/ if(item.dptr == NULL) break; /*inline cmpdatum*/ n = key.dsize; if(n != item.dsize) if( (n - item.dsize) <= 0 ) continue; else { } else { if(n == 0) continue; p1 = key.dptr; p2 = item.dptr; do if(*p1++ != *p2++) if((*--p1 - *--p2) > 0) goto keep_going; else continue; while(--n); continue; } keep_going: /*end inline cmpdatum*/ /*if(cmpdatum(key, item) <= 0) continue;*/ if (f) { bitem = item; j=i; f = 0; } else { /* if(cmpdatum(bitem, item) < 0)*/ n = bitem.dsize; if(n != item.dsize) { if((n - item.dsize) <0) { bitem = item; j=i; } } else if (n != 0) { p1 = bitem.dptr; p2 = item.dptr; do if(*p1++ != *p2++) { if((*--p1 - *--p2) <0) { bitem = item; j=i; } break; } while(--n); } } } if(f == 0) { db->dbm_keyptr = j + 2; db->dbm_blkptr = db->dbm_blkno; return (bitem); } /*really need hash at this point*/ /*if he gave us a key we have already calculated the hash*/ /*if not get it*/ if (inkey.dptr == NULL) hash=dcalchash(key); hash = dbm_hashinc(db,hash); if(hash == 0) return (item); /*null*/ /*get first item on next page in hash table order*/ return (dbm_firsthash(db, hash)); }
int dbm_store(DBM *db, datum key, datum dat, int replace) { int i; datum item, item1; char ovfbuf[PBLKSIZ]; if (dbm_error(db)) return (-1); if (dbm_rdonly(db)) { errno = EPERM; return (-1); } loop: dbm_access(db, dcalchash(key)); if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) { if (!replace) return (1); if (!delitem(db->dbm_pagbuf, i)) { db->dbm_flags |= _DBM_IOERR; return (-1); } } if (!additem(db->dbm_pagbuf, key, dat)) goto split; db->dbm_pagbno = db->dbm_blkno; if (dbm_defwrite(db)) { dbm_setdirty(db); } else { (void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET); if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; return (-1); } } return (0); split: if (key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; errno = ENOSPC; return (-1); } bzero(ovfbuf, PBLKSIZ); for (i=0;;) { item = makdatum(db->dbm_pagbuf, i); if (item.dptr == NULL) break; if (dcalchash(item) & (db->dbm_hmask+1)) { item1 = makdatum(db->dbm_pagbuf, i+1); if (item1.dptr == NULL) { /*(void) fprintf(stderr, "ndbm: split not paired\n");*/ db->dbm_flags |= _DBM_IOERR; break; } if (!additem(ovfbuf, item, item1) || !delitem(db->dbm_pagbuf, i)) { db->dbm_flags |= _DBM_IOERR; return (-1); } continue; } i += 2; } db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET); if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; return (-1); } dbm_clrdirty(db); /*clear dirty*/ (void) lseek(db->dbm_pagf, (long)((db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ), L_SET); if (write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; return (-1); } if (setbit(db) < 0) { db->dbm_flags |= _DBM_IOERR; return (-1); } goto loop; }