diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-07-19 12:01:48 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-07-19 12:58:16 +0300 |
commit | 85f1e72da83e3078e2ae1f78093ef0966e43cec1 (patch) | |
tree | b00707979e9088d5f7b7880d438260eb063c9160 /src/gdbmerrno.c | |
parent | 8e83f209342e2b035bbb19efa87ec5295158ef65 (diff) | |
download | gdbm-85f1e72da83e3078e2ae1f78093ef0966e43cec1.tar.gz gdbm-85f1e72da83e3078e2ae1f78093ef0966e43cec1.tar.bz2 |
Implement gdbm_recover function
* configure.ac: Don't check for rename.
* src/Makefile.am (libgdbm_la_SOURCES): Add recover.c
* src/recover.c: New file.
* src/bucket.c (_gdbm_get_bucket): Remove extra space before [
* src/err.c (prerror): Take additional argument
(gdbm_perror): Print system errno if necessary.
* src/gdbm.h.in (GDBM_CLOERROR): New flag.
(gdbm_fd_open, gdbm_copy_meta): New proto.
(gdbm_last_syserr,gdbm_db_strerror,gdbm_recover): New proto.
(gdbm_syserr): New extern.
(gdbm_recovery): New struct.
(GDBM_RCVR_DEFAULT,GDBM_RCVR_ERRFUN)
(GDBM_RCVR_MAX_FAILED_KEYS)
(GDBM_RCVR_MAX_FAILED_BUCKETS)
(GDBM_RCVR_MAX_FAILURES)
(GDBM_RCVR_BACKUP): New flags.
(GDBM_BACKUP_FAILED): New error code.
* src/gdbmclose.c (gdbm_close): Work correctly if dbf->desc == -1.
* src/gdbmcount.c (gdbm_count): Remove spurious sorting.
Use _gdbm_next_bucket_dir for iterating over the buckets.
* src/gdbmdefs.h (struct gdbm_file_info)<last_syserror>
<last_errstr>: New members.
* src/gdbmerrno.c (gdbm_set_errno): Set last_syserror as well.
(gdbm_clear_error): Reset last_syserror.
(gdbm_last_syserr): New function.
(gdbm_errlist): New entry for GDBM_BACKUP_FAILED.
(gdbm_db_strerror): New function.
(gdbm_syserr): New global.
* src/gdbmload.c (get_parms): Buffer can be NULL.
* src/gdbmopen.c (gdbm_fd_open): New function.
(gdbm_open): Rewrite as a wrapper over gdbm_fd_open.
* src/gdbmreorg.c (gdbm_reorganize): Rewrite as a wrapper
over gdbm_recover.
* src/proto.h (_gdbm_next_bucket_dir): New proto.
* src/gdbmtool.c: New command: recover.
* tests/.gitignore: Add gtrecover
* tests/gtrecover.c: New test program.
* tests/Makefile.am: Build gtrecover
Diffstat (limited to 'src/gdbmerrno.c')
-rw-r--r-- | src/gdbmerrno.c | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/src/gdbmerrno.c b/src/gdbmerrno.c index 8882489..1c94872 100644 --- a/src/gdbmerrno.c +++ b/src/gdbmerrno.c @@ -32,7 +32,14 @@ gdbm_set_errno (GDBM_FILE dbf, gdbm_error ec, int fatal) { if (dbf) { + free (dbf->last_errstr); + dbf->last_errstr = NULL; + dbf->last_error = ec; + if (gdbm_syserr[ec]) + dbf->last_syserror = errno; + else + dbf->last_syserror = 0; dbf->need_recovery = fatal; } gdbm_errno = ec; @@ -51,6 +58,17 @@ gdbm_last_errno (GDBM_FILE dbf) } int +gdbm_last_syserr (GDBM_FILE dbf) +{ + if (!dbf) + { + errno = EINVAL; + return -1; + } + return dbf->last_syserror; +} + +int gdbm_needs_recovery (GDBM_FILE dbf) { if (!dbf) @@ -62,8 +80,13 @@ gdbm_needs_recovery (GDBM_FILE dbf) void gdbm_clear_error (GDBM_FILE dbf) { - if (dbf) - dbf->last_error = GDBM_NO_ERROR; + if (dbf) + { + dbf->last_error = GDBM_NO_ERROR; + dbf->last_syserror = 0; + free (dbf->last_errstr); + dbf->last_errstr = NULL; + } } /* this is not static so that applications may access the array if they @@ -99,7 +122,8 @@ const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = { [GDBM_NO_DBNAME] = N_("Database name not given"), [GDBM_ERR_FILE_OWNER] = N_("Failed to restore file owner"), [GDBM_ERR_FILE_MODE] = N_("Failed to restore file mode"), - [GDBM_NEED_RECOVERY] = N_("Database needs recovery") + [GDBM_NEED_RECOVERY] = N_("Database needs recovery"), + [GDBM_BACKUP_FAILED] = N_("Failed to create backup copy") }; const char * @@ -114,3 +138,47 @@ gdbm_strerror (gdbm_error error) return gettext (gdbm_errlist[(int)error]); } } + +char const * +gdbm_db_strerror (GDBM_FILE dbf) +{ + if (!dbf->last_errstr) + { + char const *errstr; + + if (dbf->last_error == GDBM_MALLOC_ERROR) + return _("Out of memory"); + + if ((dbf->last_error < _GDBM_MIN_ERRNO) + || (dbf->last_error > _GDBM_MAX_ERRNO)) + errstr = _("Unknown error"); + else + errstr = gettext (gdbm_errlist[dbf->last_error]); + + if (dbf->last_syserror) + { + char const *syserrstr = strerror (dbf->last_syserror); + size_t len = strlen (errstr) + strlen (syserrstr) + 2; + dbf->last_errstr = malloc (len + 1); + if (!dbf->last_errstr) + return errstr; + + strcpy (dbf->last_errstr, errstr); + strcat (dbf->last_errstr, ": "); + strcat (dbf->last_errstr, syserrstr); + } + else + return errstr; + } + return dbf->last_errstr; +} + +int const gdbm_syserr[_GDBM_MAX_ERRNO+1] = { + [GDBM_FILE_OPEN_ERROR] = 1, + [GDBM_FILE_WRITE_ERROR] = 1, + [GDBM_FILE_SEEK_ERROR] = 1, + [GDBM_FILE_READ_ERROR] = 1, + [GDBM_FILE_STAT_ERROR] = 1, + [GDBM_BACKUP_FAILED] = 1 +}; + |