diff options
-rw-r--r-- | configure.ac | 10 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/debug.c | 106 | ||||
-rw-r--r-- | src/findkey.c | 19 | ||||
-rw-r--r-- | src/gdbm.h.in | 23 | ||||
-rw-r--r-- | src/gdbmdefs.h | 37 | ||||
-rw-r--r-- | src/gdbmfetch.c | 7 | ||||
-rw-r--r-- | src/gdbmopen.c | 39 | ||||
-rw-r--r-- | src/gdbmseq.c | 15 | ||||
-rw-r--r-- | src/gdbmstore.c | 15 | ||||
-rw-r--r-- | src/gdbmtool.c | 383 | ||||
-rw-r--r-- | src/gdbmtool.h | 2 | ||||
-rw-r--r-- | src/gram.y | 4 | ||||
-rw-r--r-- | src/hash.c | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 4 | ||||
-rw-r--r-- | tests/gtload.c | 33 |
16 files changed, 594 insertions, 106 deletions
diff --git a/configure.ac b/configure.ac index da5b938..4b23931 100644 --- a/configure.ac +++ b/configure.ac @@ -176,10 +176,16 @@ AM_CONDITIONAL([GDBM_COND_READLINE], [test "$status_readline" = "yes"]) # Additional debugging AC_ARG_ENABLE([debug], AC_HELP_STRING([--enable-debug], - [provide additional debugging functions]), + [provide additional debugging information]), [status_debug=$withval], [status_debug=no]) +AC_SUBST([GDBM_DEBUG_ENABLE]) +if test "$status_debug" = "yes"; then + GDBM_DEBUG_ENABLE=1 +else + GDBM_DEBUG_ENABLE=0 +fi AM_CONDITIONAL([GDBM_COND_DEBUG_ENABLE], [test "$status_debug" = "yes"]) # Initialize the test suite. @@ -197,7 +203,7 @@ Compatibility library ......................... $status_compat Compatibility export tool ..................... $status_export Memory mapped I/O ............................. $mapped_io GNU Readline .................................. $status_readline -Debugging functions ........................... $status_debug +Debugging support ............................. $status_debug ******************************************************************* EOF diff --git a/src/Makefile.am b/src/Makefile.am index 0eed6e3..a30efc4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -68,7 +68,6 @@ libgdbm_la_SOURCES = \ if GDBM_COND_DEBUG_ENABLE libgdbm_la_SOURCES += debug.c - AM_CPPFLAGS += -DGDBM_DEBUG_ENABLE=1 endif libgdbm_la_LDFLAGS = -version-info $(VI_CURRENT):$(VI_REVISION):$(VI_AGE) diff --git a/src/debug.c b/src/debug.c index ceb0f02..d13d48c 100644 --- a/src/debug.c +++ b/src/debug.c @@ -17,6 +17,112 @@ #include "autoconf.h" #include "gdbmdefs.h" +gdbm_debug_printer_t gdbm_debug_printer; +int gdbm_debug_flags; + +struct gdbm_debug_token_desc +{ + char const *name; + int flag; +}; + +struct gdbm_debug_token_desc const gdbm_debug_token_tab[] = { + { "err", GDBM_DEBUG_ERR }, + { "open", GDBM_DEBUG_OPEN }, + { "store", GDBM_DEBUG_STORE }, + { "read", GDBM_DEBUG_READ }, + { "lookup", GDBM_DEBUG_LOOKUP }, + { "all", GDBM_DEBUG_ALL }, + { NULL, 0 } +}; + +int +gdbm_debug_token (char const *tok) +{ + int i; + + for (i = 0; gdbm_debug_token_tab[i].name; i++) + if (strcmp (gdbm_debug_token_tab[i].name, tok) == 0) + return gdbm_debug_token_tab[i].flag; + + return 0; +} + +void +gdbm_debug_parse_state (int (*f) (void *, int, char const *), void *d) +{ + int i; + + for (i = 0; gdbm_debug_token_tab[i].name; i++) + { + if (gdbm_debug_token_tab[i].flag == GDBM_DEBUG_ALL) + continue; + if (gdbm_debug_flags & gdbm_debug_token_tab[i].flag) + { + if (f (d, gdbm_debug_token_tab[i].flag, gdbm_debug_token_tab[i].name)) + break; + } + } +} + +#define DATBUFSIZE 69 + +static int +datbuf_format (char vbuf[DATBUFSIZE], const char *buf, size_t size) +{ + char *p = vbuf; + char *q = vbuf + 51; + int i; + size_t j = 0; + + for (i = 0; i < 16; i++) + { + unsigned c; + if (j < size) + { + c = *(const unsigned char*)buf++; + j++; + } + else + c = 0; + sprintf(p, "%02X ", c); + p += 3; + *q++ = isprint(c) ? c : '.'; + if (i == 7) + { + *p++ = ' '; + *q++ = ' '; + } + } + *p++ = ' '; + *p = ' '; + *q = 0; + return j; +} + +void +gdbm_debug_datum (datum dat, char const *pfx) +{ + char const *buf = dat.dptr; + size_t size = dat.dsize; + char vbuf[DATBUFSIZE]; + + if (!buf) + { + gdbm_debug_printer ("%s%s\n", pfx, "NULL"); + return; + } + + while (size) + { + size_t rd = datbuf_format (vbuf, buf, size); + gdbm_debug_printer ("%s%s\n", pfx, vbuf); + size -= rd; + buf += rd; + } +} + + struct hook_list { struct hook_list *next; diff --git a/src/findkey.c b/src/findkey.c index 1f56083..a757d92 100644 --- a/src/findkey.c +++ b/src/findkey.c @@ -107,8 +107,14 @@ _gdbm_findkey (GDBM_FILE dbf, datum key, char **ret_dptr, int *ret_hash_val) int home_loc; /* The home location in the bucket. */ int key_size; /* Size of the key on the file. */ + GDBM_DEBUG_DATUM (GDBM_DEBUG_LOOKUP, key, "%s: fetching key:", dbf->name); + /* Compute hash value and load proper bucket. */ _gdbm_hash_key (dbf, key, &new_hash_val, &bucket_dir, &elem_loc); + + GDBM_DEBUG (GDBM_DEBUG_LOOKUP, "%s: location = %#4x:%d:%d", dbf->name, + new_hash_val, bucket_dir, elem_loc); + if (ret_hash_val) *ret_hash_val = new_hash_val; if (_gdbm_get_bucket (dbf, bucket_dir)) @@ -121,9 +127,10 @@ _gdbm_findkey (GDBM_FILE dbf, datum key, char **ret_dptr, int *ret_hash_val) && dbf->cache_entry->ca_data.dptr != NULL && memcmp (dbf->cache_entry->ca_data.dptr, key.dptr, key.dsize) == 0) { + GDBM_DEBUG (GDBM_DEBUG_LOOKUP, "%s: found in cache", dbf->name); /* This is it. Return the cache pointer. */ if (ret_dptr) - *ret_dptr = dbf->cache_entry->ca_data.dptr+key.dsize; + *ret_dptr = dbf->cache_entry->ca_data.dptr + key.dsize; return dbf->cache_entry->ca_data.elem_loc; } @@ -150,10 +157,15 @@ _gdbm_findkey (GDBM_FILE dbf, datum key, char **ret_dptr, int *ret_hash_val) The only way to tell is to read it. */ file_key = _gdbm_read_entry (dbf, elem_loc); if (!file_key) - return -1; + { + GDBM_DEBUG (GDBM_DEBUG_LOOKUP, "%s: error reading entry: %s", + dbf->name, gdbm_db_strerror (dbf)); + return -1; + } if (memcmp (file_key, key.dptr, key_size) == 0) { /* This is the item. */ + GDBM_DEBUG (GDBM_DEBUG_LOOKUP, "%s: found", dbf->name); if (ret_dptr) *ret_dptr = file_key + key.dsize; return elem_loc; @@ -167,9 +179,12 @@ _gdbm_findkey (GDBM_FILE dbf, datum key, char **ret_dptr, int *ret_hash_val) bucket_hash_val = dbf->bucket->h_table[elem_loc].hash_value; } } + GDBM_DEBUG (GDBM_DEBUG_LOOKUP, "%s: next location = %#4x:%d:%d", + dbf->name, bucket_hash_val, bucket_dir, elem_loc); } /* If we get here, we never found the key. */ + GDBM_DEBUG (GDBM_DEBUG_LOOKUP, "%s: not found", dbf->name); gdbm_set_errno (dbf, GDBM_ITEM_NOT_FOUND, FALSE); return -1; diff --git a/src/gdbm.h.in b/src/gdbm.h.in index 4ee3a11..3d3a7d0 100644 --- a/src/gdbm.h.in +++ b/src/gdbm.h.in @@ -240,6 +240,29 @@ extern const char *gdbm_db_strerror (GDBM_FILE dbf); extern int gdbm_version_cmp (int const a[], int const b[]); +#if @GDBM_DEBUG_ENABLE@ +# define GDBM_DEBUG_ENABLE 1 + +typedef void (*gdbm_debug_printer_t) (char const *, ...); +extern gdbm_debug_printer_t gdbm_debug_printer; +extern int gdbm_debug_flags; + +# define GDBM_DEBUG_ERR 0x00000001 +# define GDBM_DEBUG_OPEN 0x00000002 +# define GDBM_DEBUG_READ 0x00000004 +# define GDBM_DEBUG_STORE 0x00000008 +# define GDBM_DEBUG_LOOKUP 0x00000010 + +# define GDBM_DEBUG_ALL 0xffffffff + +extern int gdbm_debug_token (char const *tok); +extern void gdbm_debug_parse_state (int (*f) (void *, int, char const *), + void *d); + +extern void gdbm_debug_datum (datum dat, char const *pfx); + +#endif + # if defined(__cplusplus) || defined(c_plusplus) } # endif diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h index 035fbbe..631c9cd 100644 --- a/src/gdbmdefs.h +++ b/src/gdbmdefs.h @@ -253,6 +253,41 @@ struct gdbm_file_info /* Debugging hooks */ #ifdef GDBM_DEBUG_ENABLE +#if __STDC_VERSION__ < 199901L +# if __GNUC__ >= 2 +# define __func__ __FUNCTION__ +# else +# define __func__ "<unknown>" +# endif +#endif + +#define _gdbm_str_(s) #s +#define _gdbm_cat_(a,b) a ":" _gdbm_str_(b) +#define __gdbm_locus__ _gdbm_cat_(__FILE__,__LINE__) + +# define GDBM_DEBUG(flags, fmt, ...) \ + do \ + { \ + if (gdbm_debug_printer && gdbm_debug_flags & (flags)) \ + SAVE_ERRNO (gdbm_debug_printer (__gdbm_locus__ ":%s: " fmt "\n", \ + __func__, __VA_ARGS__)); \ + } \ + while (0) + +# define GDBM_DEBUG_DATUM(flags, dat, fmt, ...) \ + do \ + { \ + if (gdbm_debug_printer && gdbm_debug_flags & (flags)) \ + { \ + SAVE_ERRNO( \ + gdbm_debug_printer (__gdbm_locus__ ":%s: " fmt "\n", \ + __func__, __VA_ARGS__); \ + gdbm_debug_datum (dat, __gdbm_locus__": "); \ + ); \ + } \ + } \ + while (0) + typedef int (*gdbm_debug_hook) (char const *, int, char const *, void *); extern void _gdbm_debug_hook_install (char const *, gdbm_debug_hook, void *); extern void _gdbm_debug_hook_remove (char const *); @@ -264,6 +299,8 @@ extern int _gdbm_debug_hook_val (char const *); # define GDBM_DEBUG_ALLOC(id, stmt) \ (GDBM_DEBUG_HOOK(id) ? NULL : (stmt)) #else +# define GDBM_DEBUG(flags, fmt, ...) +# define GDBM_DEBUG_DATUM(flags, dat, fmt, ...) # define GDBM_DEBUG_HOOK(id) 0 # define GDBM_DEBUG_OVERRIDE(id, stmt) (stmt) # define GDBM_DEBUG_ALLOC(id, stmt) (stmt) diff --git a/src/gdbmfetch.c b/src/gdbmfetch.c index 8deee9c..4710cda 100644 --- a/src/gdbmfetch.c +++ b/src/gdbmfetch.c @@ -33,6 +33,8 @@ gdbm_fetch (GDBM_FILE dbf, datum key) int elem_loc; /* The location in the bucket. */ char *find_data; /* Returned from find_key. */ + GDBM_DEBUG_DATUM (GDBM_DEBUG_READ, key, "%s: fetching key:", dbf->name); + /* Set the default return value. */ return_val.dptr = NULL; return_val.dsize = 0; @@ -61,7 +63,12 @@ gdbm_fetch (GDBM_FILE dbf, datum key) return return_val; } memcpy (return_val.dptr, find_data, return_val.dsize); + + GDBM_DEBUG_DATUM (GDBM_DEBUG_READ, return_val, + "%s: found", dbf->name); } + else + GDBM_DEBUG (GDBM_DEBUG_READ, "%s: key not found", dbf->name); return return_val; } diff --git a/src/gdbmopen.c b/src/gdbmopen.c index 3891b7c..ce739c2 100644 --- a/src/gdbmopen.c +++ b/src/gdbmopen.c @@ -115,7 +115,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, dbf->fast_write = TRUE; /* Default to setting fast_write. */ dbf->file_locking = TRUE; /* Default to doing file locking. */ dbf->central_free = FALSE; /* Default to not using central_free. */ - dbf->coalesce_blocks = FALSE; /* Default to not coalescing blocks. */ + dbf->coalesce_blocks = FALSE; /* Default to not coalesce blocks. */ dbf->need_recovery = FALSE; dbf->last_error = GDBM_NO_ERROR; @@ -186,6 +186,8 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, flags &= ~GDBM_BSEXACT; } compute_directory_size (dbf, block_size, &dir_size, &dir_bits); + GDBM_DEBUG (GDBM_DEBUG_OPEN, "%s: computed dir_size=%d, dir_bits=%d", + dbf->name, dir_size, dir_bits); /* Check for correct block_size. */ if (dir_size != block_size) { @@ -200,6 +202,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, else block_size = dir_size; } + GDBM_DEBUG (GDBM_DEBUG_OPEN, "%s: block_size=%d", dbf->name, block_size); /* Get space for the file header. It will be written to disk, so make sure there's no garbage in it. */ @@ -312,6 +315,9 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, rc = _gdbm_full_read (dbf, &partial_header, sizeof (gdbm_file_header)); if (rc) { + GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_OPEN, + "%s: error reading partial header: %s", + dbf->name, strerror (errno)); if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; SAVE_ERRNO (gdbm_close (dbf)); @@ -323,6 +329,10 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, if (partial_header.header_magic != GDBM_MAGIC && partial_header.header_magic != GDBM_OMAGIC) { + GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_OPEN, + "%s: unexpected magic: %#4x", + dbf->name, partial_header.header_magic); + if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; gdbm_close (dbf); @@ -347,6 +357,9 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, dbf->header = (gdbm_file_header *) malloc (partial_header.block_size); if (dbf->header == NULL) { + GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_OPEN, + "%s: can't allocate header", + dbf->name); if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; gdbm_close (dbf); @@ -355,9 +368,12 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, } memcpy (dbf->header, &partial_header, sizeof (gdbm_file_header)); rc = _gdbm_full_read (dbf, &dbf->header->avail.av_table[1], - dbf->header->block_size-sizeof (gdbm_file_header)); + dbf->header->block_size - sizeof (gdbm_file_header)); if (rc) { + GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_OPEN, + "%s: error reading av_table", + dbf->name); if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; SAVE_ERRNO (gdbm_close (dbf)); @@ -369,6 +385,9 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, dbf->dir = (off_t *) malloc (dbf->header->dir_size); if (dbf->dir == NULL) { + GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_OPEN, + "%s: can't allocate directory", + dbf->name); if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; gdbm_close (dbf); @@ -380,6 +399,9 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, file_pos = __lseek (dbf, dbf->header->dir, SEEK_SET); if (file_pos != dbf->header->dir) { + GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_OPEN, + "%s: __lseek: %s", + dbf->name, strerror (errno)); if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; SAVE_ERRNO (gdbm_close (dbf)); @@ -390,6 +412,9 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, rc = _gdbm_full_read (dbf, dbf->dir, dbf->header->dir_size); if (rc) { + GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_OPEN, + "%s: error reading dir: %s", + dbf->name, strerror (errno)); if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; SAVE_ERRNO (gdbm_close (dbf)); @@ -407,6 +432,10 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, else { /* gdbm_errno should already be set. */ + GDBM_DEBUG (GDBM_DEBUG_ERR|GDBM_DEBUG_OPEN, + "%s: _gdbm_mapped_init failed: %s", + dbf->name, strerror (errno)); + if (!(flags & GDBM_CLOERROR)) dbf->desc = -1; SAVE_ERRNO (gdbm_close (dbf)); @@ -424,7 +453,9 @@ gdbm_fd_open (int fd, const char *file_name, int block_size, dbf->directory_changed = FALSE; dbf->bucket_changed = FALSE; dbf->second_changed = FALSE; - + + GDBM_DEBUG (GDBM_DEBUG_ALL, "%s: opened successfully", dbf->name); + /* Everything is fine, return the pointer to the file information structure. */ return dbf; @@ -457,7 +488,7 @@ gdbm_open (const char *file, int block_size, int flags, int mode, int fd; /* additional bits for open(2) flags */ int fbits = 0; - + switch (flags & GDBM_OPENMASK) { case GDBM_READER: diff --git a/src/gdbmseq.c b/src/gdbmseq.c index 4320366..08a8f10 100644 --- a/src/gdbmseq.c +++ b/src/gdbmseq.c @@ -101,6 +101,8 @@ gdbm_firstkey (GDBM_FILE dbf) /* Set the default return value for not finding a first entry. */ return_val.dptr = NULL; + GDBM_DEBUG (GDBM_DEBUG_READ, "%s: getting first key", dbf->name); + /* Return immediately if the database needs recovery */ GDBM_ASSERT_CONSISTENCY (dbf, return_val); @@ -113,6 +115,11 @@ gdbm_firstkey (GDBM_FILE dbf) /* Look for first entry. */ get_next_key (dbf, -1, &return_val); + if (return_val.dptr) + GDBM_DEBUG_DATUM (GDBM_DEBUG_READ, return_val, "%s: found", dbf->name); + else + GDBM_DEBUG (GDBM_DEBUG_READ, "%s: key not found", dbf->name); + return return_val; } @@ -128,6 +135,8 @@ gdbm_nextkey (GDBM_FILE dbf, datum key) /* Set the default return value for no next entry. */ return_val.dptr = NULL; + GDBM_DEBUG_DATUM (GDBM_DEBUG_READ, key, "%s: getting next key", dbf->name); + /* Return immediately if the database needs recovery */ GDBM_ASSERT_CONSISTENCY (dbf, return_val); @@ -137,6 +146,7 @@ gdbm_nextkey (GDBM_FILE dbf, datum key) /* Do we have a valid key? */ if (key.dptr == NULL) { + GDBM_DEBUG (GDBM_DEBUG_READ, "%s: key not found", dbf->name); gdbm_set_errno (dbf, GDBM_ITEM_NOT_FOUND, FALSE); /* FIXME: special error code perhaps */ return return_val; } @@ -148,5 +158,10 @@ gdbm_nextkey (GDBM_FILE dbf, datum key) /* Find the next key. */ get_next_key (dbf, elem_loc, &return_val); + if (return_val.dptr) + GDBM_DEBUG_DATUM (GDBM_DEBUG_READ, return_val, "%s: found", dbf->name); + else + GDBM_DEBUG (GDBM_DEBUG_READ, "%s: key not found", dbf->name); + return return_val; } diff --git a/src/gdbmstore.c b/src/gdbmstore.c index 1d7c648..050b0a9 100644 --- a/src/gdbmstore.c +++ b/src/gdbmstore.c @@ -47,12 +47,16 @@ gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags) int new_size; /* Used in allocating space. */ int rc; + GDBM_DEBUG_DATUM (GDBM_DEBUG_STORE, key, "%s: storing key:", dbf->name); + /* Return immediately if the database needs recovery */ GDBM_ASSERT_CONSISTENCY (dbf, -1); /* First check to make sure this guy is a writer. */ if (dbf->read_write == GDBM_READER) { + GDBM_DEBUG (GDBM_DEBUG_STORE|GDBM_DEBUG_ERR, + "%s: can't store: not a writer", dbf->name); gdbm_set_errno (dbf, GDBM_READER_CANT_STORE, FALSE); return -1; } @@ -61,6 +65,8 @@ gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags) NULL dptr returned by a lookup procedure indicates an error. */ if ((key.dptr == NULL) || (content.dptr == NULL)) { + GDBM_DEBUG (GDBM_DEBUG_STORE|GDBM_DEBUG_ERR, + "%s: can't store: invalid key or content", dbf->name); gdbm_set_errno (dbf, GDBM_ILLEGAL_DATA, FALSE); return -1; } @@ -97,6 +103,8 @@ gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags) } else { + GDBM_DEBUG (GDBM_DEBUG_STORE|GDBM_DEBUG_ERR, + "%s: cannot replace", dbf->name); gdbm_set_errno (dbf, GDBM_CANNOT_REPLACE, FALSE); return 1; } @@ -148,6 +156,8 @@ gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags) __lseek (dbf, file_adr, SEEK_SET)); if (file_pos != file_adr) { + GDBM_DEBUG (GDBM_DEBUG_STORE|GDBM_DEBUG_ERR, + "%s: lseek: %s", dbf->name, strerror (errno)); gdbm_set_errno (dbf, GDBM_FILE_SEEK_ERROR, TRUE); _gdbm_fatal (dbf, _("lseek error")); return -1; @@ -157,6 +167,8 @@ gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags) _gdbm_full_write (dbf, key.dptr, key.dsize)); if (rc) { + GDBM_DEBUG (GDBM_DEBUG_STORE|GDBM_DEBUG_ERR, + "%s: writing key: %s", dbf->name, strerror (errno)); gdbm_set_errno (dbf, rc, TRUE); _gdbm_fatal (dbf, gdbm_strerror (rc)); return -1; @@ -167,6 +179,9 @@ gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags) content.dptr, content.dsize)); if (rc) { + GDBM_DEBUG (GDBM_DEBUG_STORE|GDBM_DEBUG_ERR, + "%s: writing content: %s", + dbf->name, strerror (errno)); gdbm_set_errno (dbf, rc, TRUE); _gdbm_fatal (dbf, gdbm_strerror (rc)); return -1; diff --git a/src/gdbmtool.c b/src/gdbmtool.c index 97ba0c1..c3d5009 100644 --- a/src/gdbmtool.c +++ b/src/gdbmtool.c @@ -181,9 +181,9 @@ print_bucket (FILE *fp, hash_bucket *bucket, const char *mesg, ...) } fprintf (fp, _("\nAvail count = %1d\n"), bucket->av_count); - fprintf (fp, _("Avail adr size\n")); + fprintf (fp, _("Address size\n")); for (index = 0; index < bucket->av_count; index++) - fprintf (fp, "%9lu%9d\n", + fprintf (fp, "%11lu%9d\n", (unsigned long) bucket->bucket_avail[index].av_adr, bucket->bucket_avail[index].av_size); } @@ -357,11 +357,14 @@ get_screen_lines () void open_handler (struct handler_param *param) { - if (opendb (PARAM_STRING (param, 0)) == 0) + char *name = tildexpand (PARAM_STRING (param, 0)); + if (opendb (name) == 0) { free (file_name); - file_name = estrdup (PARAM_STRING (param, 0)); + file_name = name; } + else + free (name); } /* Close database */ @@ -446,7 +449,7 @@ fetch_handler (struct handler_param *param) free (return_data.dptr); } else if (gdbm_errno == GDBM_ITEM_NOT_FOUND) - fprintf (stderr, _("No such item found.\n")); + terror ("%s", _("No such item found.")); else terror (_("Can't fetch data: %s"), gdbm_strerror (gdbm_errno)); } @@ -458,7 +461,7 @@ store_handler (struct handler_param *param) if (gdbm_store (gdbm_file, PARAM_DATUM (param, 0), PARAM_DATUM (param, 1), GDBM_REPLACE) != 0) - fprintf (stderr, _("Item not inserted.\n")); + terror ("%s", _("Item not inserted.")); } /* first - begin iteration */ @@ -513,7 +516,7 @@ nextkey_handler (struct handler_param *param) } else if (gdbm_errno == GDBM_ITEM_NOT_FOUND) { - fprintf (stderr, _("No such item found.\n")); + terror ("%s", _("No such item found.")); free (key_data.dptr); key_data.dptr = NULL; } @@ -526,9 +529,9 @@ void reorganize_handler (struct handler_param *param GDBM_ARG_UNUSED) { if (gdbm_reorganize (gdbm_file)) - fprintf (stderr, _("Reorganization failed.\n")); + terror ("%s", _("Reorganization failed.")); else - fprintf (stderr, _("Reorganization succeeded.\n")); + fprintf (param->fp, _("Reorganization succeeded.")); } static void @@ -715,7 +718,7 @@ print_bucket_begin (struct handler_param *param, size_t *exp_count) if (temp >= GDBM_DIR_COUNT (gdbm_file)) { - fprintf (stderr, _("Not a bucket.\n")); + terror (_("Not a bucket.")); return 1; } _gdbm_get_bucket (gdbm_file, temp); @@ -723,7 +726,6 @@ print_bucket_begin (struct handler_param *param, size_t *exp_count) *exp_count = bucket_print_lines (gdbm_file->bucket) + 3; return 0; } - /* dir - print hash directory */ int @@ -740,7 +742,7 @@ void print_dir_handler (struct handler_param *param) { int i; - + fprintf (param->fp, _("Hash table directory.\n")); fprintf (param->fp, _(" Size = %d. Bits = %d. \n\n"), gdbm_file->header->dir_size, gdbm_file->header->dir_bits); @@ -791,15 +793,15 @@ hash_handler (struct handler_param *param) { int hashval, bucket, off; _gdbm_hash_key (gdbm_file, PARAM_DATUM (param, 0), - &hashval, &bucket, &off); + &hashval, &bucket, &off); fprintf (param->fp, _("hash value = %x, bucket #%u, slot %u"), - hashval, - hashval >> (GDBM_HASH_BITS - gdbm_file->header->dir_bits), - hashval % gdbm_file->header->bucket_elems); + hashval, + hashval >> (GDBM_HASH_BITS - gdbm_file->header->dir_bits), + hashval % gdbm_file->header->bucket_elems); } else fprintf (param->fp, _("hash value = %x"), - _gdbm_hash (PARAM_DATUM (param, 0))); + _gdbm_hash (PARAM_DATUM (param, 0))); fprintf (param->fp, ".\n"); } @@ -813,7 +815,7 @@ print_cache_begin (struct handler_param *param GDBM_ARG_UNUSED, size_t *exp_coun *exp_count = gdbm_file->bucket_cache ? gdbm_file->cache_size + 1 : 1; return 0; } - + void print_cache_handler (struct handler_param *param) { @@ -836,13 +838,13 @@ list_begin (struct handler_param *param GDBM_ARG_UNUSED, size_t *exp_count) if (exp_count) { gdbm_count_t count; - + if (gdbm_count (gdbm_file, &count)) - *exp_count = 0; + *exp_count = 0; else if (count > SIZE_T_MAX) - *exp_count = SIZE_T_MAX; + *exp_count = SIZE_T_MAX; else - *exp_count = count; + *exp_count = count; } return 0; @@ -861,18 +863,18 @@ list_handler (struct handler_param *param) data = gdbm_fetch (gdbm_file, key); if (!data.dptr) - { - terror (_("cannot fetch data; the key was:")); - datum_format (stderr, &key, dsdef[DS_KEY]); - } + { + terror (_("cannot fetch data; the key was:")); + datum_format (stderr, &key, dsdef[DS_KEY]); + } else - { - datum_format (param->fp, &key, dsdef[DS_KEY]); - fputc (' ', param->fp); - datum_format (param->fp, &data, dsdef[DS_CONTENT]); - fputc ('\n', param->fp); - free (data.dptr); - } + { + datum_format (param->fp, &key, dsdef[DS_KEY]); + fputc (' ', param->fp); + datum_format (param->fp, &data, dsdef[DS_CONTENT]); + fputc ('\n', param->fp); + free (data.dptr); + } free (key.dptr); key = nextkey; } @@ -896,20 +898,20 @@ export_handler (struct handler_param *param) int flags = GDBM_WRCREAT; int i; int filemode; - + for (i = 1; i < param->argc; i++) { if (strcmp (PARAM_STRING (param, i), "truncate") == 0) - flags = GDBM_NEWDB; + flags = GDBM_NEWDB; else if (strcmp (PARAM_STRING (param, i), "binary") == 0) - format = GDBM_DUMP_FMT_BINARY; + format = GDBM_DUMP_FMT_BINARY; else if (strcmp (PARAM_STRING (param, i), "ascii") == 0) - format = GDBM_DUMP_FMT_ASCII; + format = GDBM_DUMP_FMT_ASCII; else - { - terror (_("unrecognized argument: %s"), PARAM_STRING (param, i)); - return; - } + { + terror (_("unrecognized argument: %s"), PARAM_STRING (param, i)); + return; + } } if (variable_get ("filemode", VART_INT, (void**) &filemode)) @@ -917,7 +919,7 @@ export_handler (struct handler_param *param) if (gdbm_dump (gdbm_file, PARAM_STRING (param, 0), format, flags, filemode)) { terror (_("error dumping database: %s"), - gdbm_strerror (gdbm_errno)); + gdbm_strerror (gdbm_errno)); } } @@ -930,23 +932,23 @@ import_handler (struct handler_param *param) int meta_mask = 0; int i; int rc; - + for (i = 1; i < param->argc; i++) { if (strcmp (PARAM_STRING (param, i), "replace") == 0) - flag = GDBM_REPLACE; + flag = GDBM_REPLACE; else if (strcmp (PARAM_STRING (param, i), "nometa") == 0) - meta_mask = GDBM_META_MASK_MODE | GDBM_META_MASK_OWNER; + meta_mask = GDBM_META_MASK_MODE | GDBM_META_MASK_OWNER; else - { - terror (_("unrecognized argument: %s"), - PARAM_STRING (param, i)); - return; - } + { + terror (_("unrecognized argument: %s"), + PARAM_STRING (param, i)); + return; + } } rc = gdbm_load (&gdbm_file, PARAM_STRING (param, 0), flag, - meta_mask, &err_line); + meta_mask, &err_line); if (rc && gdbm_errno == GDBM_NO_DBNAME) { int t = open_mode; @@ -956,29 +958,29 @@ import_handler (struct handler_param *param) open_mode = t; if (rc) - return; + return; rc = gdbm_load (&gdbm_file, PARAM_STRING (param, 0), flag, - meta_mask, &err_line); + meta_mask, &err_line); } if (rc) { switch (gdbm_errno) - { - case GDBM_ERR_FILE_OWNER: - case GDBM_ERR_FILE_MODE: - terror (_("error restoring metadata: %s (%s)"), - gdbm_strerror (gdbm_errno), strerror (errno)); - break; - - default: - if (err_line) - terror ("%s:%lu: %s", PARAM_STRING (param, 0), err_line, - gdbm_strerror (gdbm_errno)); - else - terror (_("cannot load from %s: %s"), PARAM_STRING (param, 0), - gdbm_strerror (gdbm_errno)); - } + { + case GDBM_ERR_FILE_OWNER: + case GDBM_ERR_FILE_MODE: + terror (_("error restoring metadata: %s (%s)"), + gdbm_strerror (gdbm_errno), strerror (errno)); + break; + + default: + if (err_line) + terror ("%s:%lu: %s", PARAM_STRING (param, 0), err_line, + gdbm_strerror (gdbm_errno)); + else + terror (_("cannot load from %s: %s"), PARAM_STRING (param, 0), + gdbm_strerror (gdbm_errno)); + } return; } @@ -1003,6 +1005,77 @@ status_handler (struct handler_param *param) dsprint (param->fp, DS_CONTENT, dsdef[DS_CONTENT]); } +#ifdef GDBM_DEBUG_ENABLE +static int +debug_flag_printer (void *data, int flag, char const *tok) +{ + FILE *fp = data; + fprintf (fp, " %s", tok); + return 0; +} +#endif + +void +debug_handler (struct handler_param *param) +{ +#ifdef GDBM_DEBUG_ENABLE + if (param->vararg) + { + struct gdbmarg *arg; + int i; + + for (arg = param->vararg, i = 0; arg; arg = arg->next, i++) + { + if (arg->type == GDBM_ARG_STRING) + { + int flag; + int negate; + char const *tok = arg->v.string; + + if (tok[0] == '-') + { + ++tok; + negate = 1; + } + else if (tok[0] == '+') + { + ++tok; + negate = 0; + } + else + negate = 0; + + flag = gdbm_debug_token (tok); + if (flag) + { + if (negate) + gdbm_debug_flags &= ~flag; + else + gdbm_debug_flags |= flag; + } + else + terror (_("unknown debug flag: %s"), tok); + } + else + terror (_("invalid type of argument %d"), i); + } + } + else + { + fprintf (param->fp, _("Debug flags:")); + if (gdbm_debug_flags) + { + gdbm_debug_parse_state (debug_flag_printer, param->fp); + } + else + fprintf (param->fp, " %s", _("none")); + fputc ('\n', param->fp); + } +#else + terror ("%s", _("compiled without debug support")); +#endif +} + void source_handler (struct handler_param *param) { @@ -1034,6 +1107,8 @@ struct command void (*handler) (struct handler_param *param); void (*end) (void *data); struct argdef args[NARGS]; + int variadic; + int repeat; char *doc; }; @@ -1041,47 +1116,73 @@ struct command command_tab[] = { #define S(s) #s, sizeof (#s) - 1 { S(count), T_CMD, checkdb, count_handler, NULL, - { { NULL } }, N_("count (number of entries)") }, + { { NULL } }, + FALSE, + FALSE, + N_("count (number of entries)") }, { S(delete), T_CMD, checkdb, delete_handler, NULL, - { { N_("KEY"), GDBM_ARG_DATUM, DS_KEY }, { NULL } }, N_("delete a record") }, + { { N_("KEY"), GDBM_ARG_DATUM, DS_KEY }, { NULL } }, + FALSE, + FALSE, + N_("delete a record") }, { S(export), T_CMD, checkdb, export_handler, NULL, { { N_("FILE"), GDBM_ARG_STRING }, { "[truncate]", GDBM_ARG_STRING }, { "[binary|ascii]", GDBM_ARG_STRING }, { NULL } }, + FALSE, + FALSE, N_("export") }, { S(fetch), T_CMD, checkdb, fetch_handler, NULL, - { { N_("KEY"), GDBM_ARG_DATUM, DS_KEY }, { NULL } }, N_("fetch record") }, + { { N_("KEY"), GDBM_ARG_DATUM, DS_KEY }, { NULL } }, + FALSE, + FALSE, + N_("fetch record") }, { S(import), T_CMD, NULL, import_handler, NULL, { { N_("FILE"), GDBM_ARG_STRING }, { "[replace]", GDBM_ARG_STRING }, { "[nometa]" , GDBM_ARG_STRING }, { NULL } }, |