diff options
-rw-r--r-- | NEWS | 10 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | doc/gdbm.3 | 10 | ||||
-rw-r--r-- | doc/gdbm.texi | 16 | ||||
-rw-r--r-- | src/gdbm.h.in | 10 | ||||
-rw-r--r-- | src/gdbmclose.c | 16 | ||||
-rw-r--r-- | src/gdbmerrno.c | 8 | ||||
-rw-r--r-- | src/gdbmsync.c | 5 | ||||
-rw-r--r-- | src/mmap.c | 14 | ||||
-rw-r--r-- | src/proto.h | 11 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/closerr.at | 5 | ||||
-rw-r--r-- | tests/closerr.c | 56 | ||||
-rw-r--r-- | tests/gtdel.c | 8 | ||||
-rw-r--r-- | tests/gtdump.c | 8 | ||||
-rw-r--r-- | tests/gtfetch.c | 8 | ||||
-rw-r--r-- | tests/gtload.c | 7 | ||||
-rw-r--r-- | tests/gtopt.c | 8 | ||||
-rw-r--r-- | tests/gtrecover.c | 8 | ||||
-rw-r--r-- | tests/testsuite.at | 2 |
20 files changed, 178 insertions, 36 deletions
@@ -1,9 +1,17 @@ -GNU dbm NEWS -- history of user-visible changes. 2018-06-27 +GNU dbm NEWS -- history of user-visible changes. 2018-07-01 Copyright (C) 1990-2018 Free Software Foundation, Inc. See the end of file for copying conditions. Please send gdbm bug reports to <bug-gdbm@gnu.org>. +Version 1.16.90 (Git) + +* int gdbm_close and gdbm_sync + +Both functions now return 0 on success. On error, they return -1 +and set gdbm_errno and errno to the appropriate error codes. + + Version 1.16 - 2018-06-27 * Maintain sorting order of the available block list after coalescing diff --git a/configure.ac b/configure.ac index 4306bcd..3ca6252 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ m4_define([_GDBM_VERSION_MAJOR], 1) m4_define([_GDBM_VERSION_MINOR], 16) -dnl m4_define([_GDBM_VERSION_PATCH], 0) +m4_define([_GDBM_VERSION_PATCH], 90) AC_INIT([gdbm], _GDBM_VERSION_MAJOR._GDBM_VERSION_MINOR[]m4_ifdef([_GDBM_VERSION_PATCH],._GDBM_VERSION_PATCH), @@ -13,7 +13,7 @@ .\" .\" You should have received a copy of the GNU General Public License .\" along with GDBM. If not, see <http://www.gnu.org/licenses/>. */ -.TH GDBM 3 "July 8, 2016" "GDBM" "GDBM User Reference" +.TH GDBM 3 "July 1, 2018" "GDBM" "GDBM User Reference" .SH NAME GDBM \- The GNU database manager. Includes \fBdbm\fR and \fBndbm\fR compatibility. @@ -31,7 +31,7 @@ compatibility. .ti +21 .BI "void (*" fatal_func ")(const char *))"; .br -.BI "void gdbm_close (GDBM_FILE " dbf ");" +.BI "int gdbm_close (GDBM_FILE " dbf ");" .br .BI "int gdbm_store (GDBM_FILE " dbf ", datum " key ", datum " content ", int " flag ); .br @@ -45,7 +45,7 @@ compatibility. .br .BI "int gdbm_reorganize (GDBM_FILE " dbf ");" .br -.BI "void gdbm_sync (GDBM_FILE " dbf ");" +.BI "int gdbm_sync (GDBM_FILE " dbf ");" .br .BI "int gdbm_exists (GDBM_FILE " dbf ", datum " key ); .br @@ -183,7 +183,7 @@ returned from \fBgdbm_open\fR. It is important that every file opened is also closed. This is needed to update the reader/writer count on the file. This is done by: -.BI "void gdbm_close (GDBM_FILE " dbf ");" +.BI "int gdbm_close (GDBM_FILE " dbf ");" The database is used by 3 primary routines. The first stores data in the database. @@ -308,7 +308,7 @@ wait for writes to be flushed to the disk before continuing. The following routine can be used to guarantee that the database is physically written to the disk file. -.BI "void gdbm_sync (GDBM_FILE " dbf ");" +.BI "int gdbm_sync (GDBM_FILE " dbf ");" It will not return until the disk file state is syncronized with the in-memory state of the database. diff --git a/doc/gdbm.texi b/doc/gdbm.texi index b5ba53d..4a0b1a7 100644 --- a/doc/gdbm.texi +++ b/doc/gdbm.texi @@ -215,14 +215,14 @@ contains a definition of these functions. #include <gdbm.h> GDBM_FILE gdbm_open(name, block_size, flags, mode, fatal_func); -void gdbm_close(dbf); +int gdbm_close(dbf); int gdbm_store(dbf, key, content, flag); datum gdbm_fetch(dbf, key); int gdbm_delete(dbf, key); datum gdbm_firstkey(dbf); datum gdbm_nextkey(dbf, key); int gdbm_reorganize(dbf); -void gdbm_sync(dbf); +int gdbm_sync(dbf); int gdbm_exists(dbf, key); char *gdbm_strerror(errno); int gdbm_setopt(dbf, option, value, size); @@ -369,7 +369,7 @@ Copy file ownership and mode from @var{src} to @var{dst}. It is important that every file opened is also closed. This is needed to update the reader/writer count on the file: -@deftypefn {gdbm interface} void gdbm_close (GDBM_FILE @var{dbf}) +@deftypefn {gdbm interface} int gdbm_close (GDBM_FILE @var{dbf}) This function closes the @code{gdbm} file and frees all memory associated with it. The parameter is: @@ -377,6 +377,10 @@ associated with it. The parameter is: @item dbf The pointer returned by @code{gdbm_open}. @end table + +@code{Gdbm_close} returns 0 on success. On error, it sets +@code{gdbm_errno} and system @code{errno} variables to the codes +describing the error and returns -1. @end deftypefn @node Count @@ -678,7 +682,7 @@ abnormal fashion. The following function allows the programmer to make sure the disk version of the database has been completely updated with all changes to the current time. -@deftypefn {gdbm interface} void gdbm_sync (GDBM_FILE @var{dbf}) +@deftypefn {gdbm interface} int gdbm_sync (GDBM_FILE @var{dbf}) Synchronizes the changes in @var{dbf} with its disk file. The parameter is a pointer returned by @code{gdbm_open}. @@ -687,6 +691,10 @@ have been made to the database and before some long waiting time. The @code{gdbm_close} function automatically calls the equivalent of @code{gdbm_sync} so no call is needed if the database is to be closed immediately after the set of changes have been made. + +@code{Gdbm_sync} returns 0 on success. On error, it sets +@code{gdbm_errno} and system @code{errno} variables to the codes +describing the error and returns -1. @end deftypefn @node Flat files diff --git a/src/gdbm.h.in b/src/gdbm.h.in index e6bdc58..6318ad8 100644 --- a/src/gdbm.h.in +++ b/src/gdbm.h.in @@ -113,7 +113,7 @@ extern GDBM_FILE gdbm_fd_open (int fd, const char *file_name, int block_size, int flags, void (*fatal_func) (const char *)); extern GDBM_FILE gdbm_open (const char *, int, int, int, void (*)(const char *)); -extern void gdbm_close (GDBM_FILE); +extern int gdbm_close (GDBM_FILE); extern int gdbm_store (GDBM_FILE, datum, datum, int); extern datum gdbm_fetch (GDBM_FILE, datum); extern int gdbm_delete (GDBM_FILE, datum); @@ -121,7 +121,7 @@ extern datum gdbm_firstkey (GDBM_FILE); extern datum gdbm_nextkey (GDBM_FILE, datum); extern int gdbm_reorganize (GDBM_FILE); -extern void gdbm_sync (GDBM_FILE); +extern int gdbm_sync (GDBM_FILE); extern int gdbm_exists (GDBM_FILE, datum); extern int gdbm_setopt (GDBM_FILE, int, void *, int); extern int gdbm_fdesc (GDBM_FILE); @@ -225,9 +225,11 @@ extern int gdbm_copy_meta (GDBM_FILE dst, GDBM_FILE src); # define GDBM_BAD_AVAIL 34 # define GDBM_BAD_HASH_TABLE 35 # define GDBM_BAD_DIR_ENTRY 36 - +# define GDBM_FILE_CLOSE_ERROR 37 +# define GDBM_FILE_SYNC_ERROR 38 + # define _GDBM_MIN_ERRNO 0 -# define _GDBM_MAX_ERRNO GDBM_BAD_DIR_ENTRY +# define _GDBM_MAX_ERRNO GDBM_FILE_SYNC_ERROR /* This one was never used and will be removed in the future */ # define GDBM_UNKNOWN_UPDATE GDBM_UNKNOWN_ERROR diff --git a/src/gdbmclose.c b/src/gdbmclose.c index ead9187..c438ec1 100644 --- a/src/gdbmclose.c +++ b/src/gdbmclose.c @@ -26,10 +26,13 @@ Before freeing members of DBF, check and make sure that they were allocated. */ -void +int gdbm_close (GDBM_FILE dbf) { int index; /* For freeing the bucket cache. */ + int syserrno; + + gdbm_set_errno (dbf, GDBM_NO_ERROR, FALSE); if (dbf->desc != -1) { @@ -44,9 +47,12 @@ gdbm_close (GDBM_FILE dbf) if (dbf->file_locking) _gdbm_unlock_file (dbf); - close (dbf->desc); + if (close (dbf->desc)) + GDBM_SET_ERRNO (dbf, GDBM_FILE_CLOSE_ERROR, FALSE); } + syserrno = gdbm_last_syserr (dbf); + gdbm_clear_error (dbf); free (dbf->name); @@ -63,4 +69,10 @@ gdbm_close (GDBM_FILE dbf) } free (dbf->header); free (dbf); + if (gdbm_errno) + { + errno = syserrno; + return -1; + } + return 0; } diff --git a/src/gdbmerrno.c b/src/gdbmerrno.c index 8e24b82..4ce7f9d 100644 --- a/src/gdbmerrno.c +++ b/src/gdbmerrno.c @@ -136,7 +136,9 @@ const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = { [GDBM_BAD_HEADER] = N_("Malformed database file header"), [GDBM_BAD_AVAIL] = N_("Malformed avail_block"), [GDBM_BAD_HASH_TABLE] = N_("Malformed hash table"), - [GDBM_BAD_DIR_ENTRY] = N_("Invalid directory entry") + [GDBM_BAD_DIR_ENTRY] = N_("Invalid directory entry"), + [GDBM_FILE_CLOSE_ERROR] = N_("Error closing file"), + [GDBM_FILE_SYNC_ERROR] = N_("Error synchronizing file") }; const char * @@ -178,7 +180,9 @@ int const gdbm_syserr[_GDBM_MAX_ERRNO+1] = { [GDBM_FILE_SEEK_ERROR] = 1, [GDBM_FILE_READ_ERROR] = 1, [GDBM_FILE_STAT_ERROR] = 1, - [GDBM_BACKUP_FAILED] = 1 + [GDBM_BACKUP_FAILED] = 1, + [GDBM_FILE_CLOSE_ERROR] = 1, + [GDBM_FILE_SYNC_ERROR] = 1 }; /* Returns true if system errno value is meaningful for GDBM error diff --git a/src/gdbmsync.c b/src/gdbmsync.c index 5d94cbe..a8d1002 100644 --- a/src/gdbmsync.c +++ b/src/gdbmsync.c @@ -24,7 +24,7 @@ /* Make sure the database is all on disk. */ -void +int gdbm_sync (GDBM_FILE dbf) { /* Return immediately if the database needs recovery */ @@ -34,6 +34,5 @@ gdbm_sync (GDBM_FILE dbf) gdbm_set_errno (dbf, GDBM_NO_ERROR, FALSE); /* Do the sync on the file. */ - gdbm_file_sync (dbf); - + return gdbm_file_sync (dbf); } @@ -392,12 +392,16 @@ _gdbm_mapped_lseek (GDBM_FILE dbf, off_t offset, int whence) int _gdbm_mapped_sync (GDBM_FILE dbf) { + int rc; + if (dbf->mapped_region) - { - return msync (dbf->mapped_region, dbf->mapped_size, - MS_SYNC | MS_INVALIDATE); - } - return fsync (dbf->desc); + rc = msync (dbf->mapped_region, dbf->mapped_size, + MS_SYNC | MS_INVALIDATE); + else + rc = fsync (dbf->desc); + if (rc) + GDBM_SET_ERRNO (dbf, GDBM_FILE_SYNC_ERROR, TRUE); + return rc; } #endif diff --git a/src/proto.h b/src/proto.h index 22f29e4..02f6f9b 100644 --- a/src/proto.h +++ b/src/proto.h @@ -115,16 +115,21 @@ gdbm_file_seek (GDBM_FILE dbf, off_t off, int whence) #endif } -static inline void +static inline int gdbm_file_sync (GDBM_FILE dbf) { #if HAVE_MMAP - _gdbm_mapped_sync (dbf); + return _gdbm_mapped_sync (dbf); #elif HAVE_FSYNC - fsync (dbf->desc); + if (fsync (dbf->desc)) + { + GDBM_SET_ERRNO (dbf, GDBM_FILE_SYNC_ERROR, TRUE); + return 1; + } #else sync (); sync (); + return 0; #endif } diff --git a/tests/Makefile.am b/tests/Makefile.am index 827af58..dbe17dd 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -54,6 +54,7 @@ TESTSUITE_AT = \ cloexec01.at\ cloexec02.at\ cloexec03.at\ + closerr.at\ dbmcreate00.at\ dbmdel00.at\ dbmdel01.at\ @@ -108,6 +109,7 @@ if COMPAT_OPT endif check_PROGRAMS = \ + closerr\ fdop\ g_open_ce\ g_reorg_ce\ diff --git a/tests/closerr.at b/tests/closerr.at new file mode 100644 index 0000000..5f5e208 --- /dev/null +++ b/tests/closerr.at @@ -0,0 +1,5 @@ +# This file is part of GDBM testsuite. -*- autoconf -*- +AT_SETUP([gdbm_close error]) +AT_KEYWORDS([close]) +AT_CHECK(closerr,1,[],[ignore]) +AT_CLEANUP diff --git a/tests/closerr.c b/tests/closerr.c new file mode 100644 index 0000000..5bc8fdc --- /dev/null +++ b/tests/closerr.c @@ -0,0 +1,56 @@ +/* This file is part of GDBM test suite. + Copyright (C) 2018 Free Software Foundation, Inc. + + GDBM is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GDBM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GDBM. If not, see <http://www.gnu.org/licenses/>. +*/ +#include "autoconf.h" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include "gdbm.h" + +int +main (int argc, char **argv) +{ + GDBM_FILE dbf; + char dbname[] = "junk.gdbm"; + int rc; + + assert (argc == 1); + + dbf = gdbm_open (dbname, 0, GDBM_NEWDB, 0600, NULL); + if (!dbf) + { + fprintf (stderr, "gdbm_open: %s; %s\n", gdbm_strerror (gdbm_errno), + strerror (errno)); + return 1; + } + if (close (gdbm_fdesc (dbf))) + { + perror ("close"); + return 77; + } + + if (gdbm_close (dbf)) + { + fprintf (stderr, "gdbm_close: %s; %s\n", gdbm_strerror (gdbm_errno), + strerror (errno)); + return 1; + } + + return 0; +} diff --git a/tests/gtdel.c b/tests/gtdel.c index 729086c..d0c711d 100644 --- a/tests/gtdel.c +++ b/tests/gtdel.c @@ -18,6 +18,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> #include "gdbm.h" #include "progname.h" @@ -93,6 +94,11 @@ main (int argc, char **argv) rc = 2; } } - gdbm_close (dbf); + if (gdbm_close (dbf)) + { + fprintf (stderr, "gdbm_close: %s; %s\n", gdbm_strerror (gdbm_errno), + strerror (errno)); + rc = 3; + } exit (rc); } diff --git a/tests/gtdump.c b/tests/gtdump.c index dcc27ac..fb27997 100644 --- a/tests/gtdump.c +++ b/tests/gtdump.c @@ -18,6 +18,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> #include "gdbm.h" #include "progname.h" @@ -115,6 +116,11 @@ main (int argc, char **argv) exit (1); } - gdbm_close (dbf); + if (gdbm_close (dbf)) + { + fprintf (stderr, "gdbm_close: %s; %s\n", gdbm_strerror (gdbm_errno), + strerror (errno)); + exit (3); + } exit (0); } diff --git a/tests/gtfetch.c b/tests/gtfetch.c index c1ea45e..5070fcc 100644 --- a/tests/gtfetch.c +++ b/tests/gtfetch.c @@ -18,6 +18,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> #include "gdbm.h" #include "progname.h" @@ -130,6 +131,11 @@ main (int argc, char **argv) fputc ('\n', stdout); } - gdbm_close (dbf); + if (gdbm_close (dbf)) + { + fprintf (stderr, "gdbm_close: %s; %s\n", gdbm_strerror (gdbm_errno), + strerror (errno)); + rc = 3; + } exit (rc); } diff --git a/tests/gtload.c b/tests/gtload.c index 21c89b2..1493236 100644 --- a/tests/gtload.c +++ b/tests/gtload.c @@ -287,6 +287,11 @@ main (int argc, char **argv) } } } - gdbm_close (dbf); + if (gdbm_close (dbf)) + { + fprintf (stderr, "gdbm_close: %s; %s\n", gdbm_strerror (gdbm_errno), + strerror (errno)); + exit (3); + } exit (0); } diff --git a/tests/gtopt.c b/tests/gtopt.c index b461d56..236ae92 100644 --- a/tests/gtopt.c +++ b/tests/gtopt.c @@ -406,7 +406,13 @@ main (int argc, char **argv) } } - gdbm_close (dbf); + if (gdbm_close (dbf)) + { + fprintf (stderr, "gdbm_close: %s; %s\n", gdbm_strerror (gdbm_errno), + strerror (errno)); + exit (3); + } + exit (0); } diff --git a/tests/gtrecover.c b/tests/gtrecover.c index 0527c53..f5e6f97 100644 --- a/tests/gtrecover.c +++ b/tests/gtrecover.c @@ -19,6 +19,7 @@ #include <stdlib.h> #include <stdarg.h> #include <string.h> +#include <errno.h> #include "gdbm.h" #include "progname.h" #include <assert.h> @@ -119,6 +120,11 @@ main (int argc, char **argv) rc = gdbm_recover (dbf, &rcvr, rcvr_flags); - gdbm_close (dbf); + if (gdbm_close (dbf)) + { + fprintf (stderr, "gdbm_close: %s; %s\n", gdbm_strerror (gdbm_errno), + strerror (errno)); + rc = 3; + } exit (rc); } diff --git a/tests/testsuite.at b/tests/testsuite.at index b7b1e4e..efc2705 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -43,6 +43,8 @@ m4_include([delete00.at]) m4_include([delete01.at]) m4_include([delete02.at]) +m4_include([closerr.at]) + AT_BANNER([Block size selection]) m4_include([blocksize00.at]) m4_include([blocksize01.at]) |