aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--NEWS16
-rw-r--r--compat/dbmopen.c42
-rw-r--r--doc/gdbm.texinfo21
-rw-r--r--src/gdbm.h.in17
-rw-r--r--src/gdbmopen.c12
-rw-r--r--src/systems.h4
7 files changed, 99 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index e6f9515..4b16466 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2011-11-11 Sergey Poznyakoff <gray@gnu.org.ua>
+ Support close-on-exec flag for gdbm_open call.
+
+ * src/gdbm.h.in (GDBM_CLOEXEC): New flag.
+ * src/systems.h [O_CLOEXEC]: Provide a placeholder definition.
+
+ * src/gdbmopen.c (gdbm_open): Honor the GDBM_CLOEXEC flag.
+ * compat/dbmopen.c (ndbm_open_dir_file0): Mask out open mode
+ before comparing with GDBM_READER.
+ Support GDBM_CLOEXEC.
+ (dbm_open): Translate O_CLOEXEC to GDBM_CLOEXEC.
+
+ * doc/gdbm.texinfo: Document GDBM_CLOEXEC.
+
+ * NEWS: Update.
+
+2011-11-11 Sergey Poznyakoff <gray@gnu.org.ua>
+
Fix handling of NDBM databases in read-only mode.
* compat/dbmopen.c (ndbm_open_dir_file0): Open dir file in
diff --git a/NEWS b/NEWS
index 47683a6..b6bdb9e 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,22 @@ Version 1.9.90 (Git)
* Internationalization
+The following localizations are available: Finnish, German, Japanese, Polish
+and Ukrainian.
+
+* Support for close-on-exec flag in gdbm_open (see GDBM_CLOEXEC in the docs).
+
+* Bugfixes
+
+** Bug #150.
+Tolerate I/O operations returning less bytes than expected. Retry I/O
+if possible.
+
+** Bug #151
+Gdbm_open initializes with zeros the memory allocated for file header.
+
+** Fix handling of NDBM databases in read-only mode.
+
Version 1.9.1
diff --git a/compat/dbmopen.c b/compat/dbmopen.c
index 0125903..4ae55d9 100644
--- a/compat/dbmopen.c
+++ b/compat/dbmopen.c
@@ -79,7 +79,7 @@ ndbm_open_dir_file0 (const char *file_name, int pagfd, int mode)
{
if (unlink (file_name))
{
- if (mode == GDBM_READER)
+ if ((mode & GDBM_OPENMASK) == GDBM_READER)
/* Ok, try to cope with it. */
return pagfd;
else
@@ -104,7 +104,13 @@ ndbm_open_dir_file0 (const char *file_name, int pagfd, int mode)
}
else
{
- fd = open (file_name, mode == GDBM_READER ? O_RDONLY : O_RDWR);
+ int flags = (mode & GDBM_OPENMASK) == GDBM_READER ?
+ O_RDONLY : O_RDWR;
+
+ if (mode & GDBM_CLOEXEC)
+ flags |= O_CLOEXEC;
+
+ fd = open (file_name, flags);
if (fd == -1)
{
gdbm_errno = GDBM_FILE_OPEN_ERROR;
@@ -180,14 +186,20 @@ ndbm_open_dir_file (const char *base, int pagfd, int mode)
size of zero bytes, a file initialization procedure is performed,
setting up the initial structure in the file. Any error detected will
cause a return value of -1. No errors cause the return value of 0.
- NOTE: file.dir will be ignored and will always have a size of zero.
- FLAGS and MODE are the same as the open (2) call. This call will
+
+ The file.dir file is used only to ensure that the corresponding file.pag
+ was created using a compatible version of GDBM. If file.dir is a hard
+ link to file.pag, as was in GDBM 1.8.x, it is removed and recreated in
+ the right format (see above). If the database is being opened read-only,
+ the file.dir remains untouched.
+
+ FLAGS and MODE are the same as for the open(2) call. This call will
look at the FLAGS and decide what call to make to gdbm_open. For
FLAGS == O_RDONLY, it will be a GDBM_READER, if FLAGS == O_RDWR|O_CREAT,
it will be a GDBM_WRCREAT (creater and writer) and if the FLAGS == O_RDWR,
it will be a GDBM_WRITER and if FLAGS contain O_TRUNC then it will be
- a GDBM_NEWDB. All other values of FLAGS in the flags are
- ignored. */
+ a GDBM_NEWDB. The O_CLOEXEC bit raises GDBM_CLOEXEC flag.
+ All other values of FLAGS are ignored. */
DBM *
dbm_open (char *file, int flags, int mode)
@@ -195,9 +207,10 @@ dbm_open (char *file, int flags, int mode)
char *pag_file; /* Used to construct "file.pag". */
DBM *dbm = NULL;
int open_flags;
+ int f;
/* Prepare the correct name for "file.pag". */
- pag_file = (char *) malloc (strlen (file)+5);
+ pag_file = (char *) malloc (strlen (file) + 5);
if (!pag_file)
{
gdbm_errno = GDBM_MALLOC_ERROR; /* For the hell of it. */
@@ -208,18 +221,18 @@ dbm_open (char *file, int flags, int mode)
strcat (pag_file, ".pag");
/* Call the actual routine, saving the pointer to the file information. */
- flags &= O_RDONLY | O_RDWR | O_CREAT | O_TRUNC;
+ f = flags & (O_RDONLY | O_RDWR | O_CREAT | O_TRUNC);
- if (flags == O_RDONLY)
+ if (f == O_RDONLY)
{
open_flags = GDBM_READER;
mode = 0;
}
- else if (flags == (O_RDWR | O_CREAT))
+ else if (f == (O_RDWR | O_CREAT))
{
open_flags = GDBM_WRCREAT;
}
- else if ((flags & O_TRUNC) == O_TRUNC)
+ else if ((f & O_TRUNC) == O_TRUNC)
{
open_flags = GDBM_NEWDB;
}
@@ -229,6 +242,11 @@ dbm_open (char *file, int flags, int mode)
mode = 0;
}
+ if (flags & O_CLOEXEC)
+ open_flags |= GDBM_CLOEXEC;
+
+ open_flags |= GDBM_NOLOCK;
+
dbm = calloc (1, sizeof (*dbm));
if (!dbm)
{
@@ -237,7 +255,7 @@ dbm_open (char *file, int flags, int mode)
return NULL;
}
- dbm->file = gdbm_open (pag_file, 0, open_flags | GDBM_NOLOCK, mode, NULL);
+ dbm->file = gdbm_open (pag_file, 0, open_flags, mode, NULL);
/* Did we successfully open the file? */
if (dbm->file == NULL)
diff --git a/doc/gdbm.texinfo b/doc/gdbm.texinfo
index 010f6f0..1876c3a 100644
--- a/doc/gdbm.texinfo
+++ b/doc/gdbm.texinfo
@@ -296,10 +296,20 @@ The following may also be logically or'd into the database flags:
synchronized to the disk, @samp{GDBM_NOLOCK}, which prevents the library
from performing any locking on the database file, and @samp{GDBM_NOMMAP},
which disables the memory mapping mechanism. The option @samp{GDBM_FAST} is
-now obsolete, since @code{gdbm} defaults to no-sync mode. Any error detected
-will cause a return value of @samp{NULL} and an appropriate value will be in
-@code{gdbm_errno} (@pxref{Variables}). If no errors occur, a pointer to the
-@code{gdbm} file descriptor will be returned.
+now obsolete, since @code{gdbm} defaults to no-sync mode.
+
+@kwindex GDBM_CLOEXEC
+@cindex close-on-exec
+If the host @samp{open} call
+@ifhtml
+(@uref{http://www.manpagez.com/man/2/open, open(2)})
+@end ifhtml
+@ifnothtml
+(@pxref{open,,,open(2),open(2) man page})
+@end ifnothtml
+supports the @samp{O_CLOEXEC} flag, the @samp{GDBM_CLOEXEC} can be
+or'd into the flags, to enable the close-on-exec flag for the
+database file descriptor.
@item mode
File mode (see
@ifhtml
@@ -1578,7 +1588,8 @@ The functions below implement the @acronym{POSIX} @samp{ndbm} interface:
Opens a database. The @var{file} argument is the full name of the
database file to be opened. The function opens two files:
@file{@var{file}.pag} and @file{@var{file}.dir}. The @var{flags} and
-@var{mode} arguments have the same meaning as the second and third arguments of
+@var{mode} arguments have the same meaning as the second and third
+arguments of
@ifhtml
@uref{http://www.manpagez.com/man/2/open,,open(2)},
@end ifhtml
diff --git a/src/gdbm.h.in b/src/gdbm.h.in
index 2420774..21168de 100644
--- a/src/gdbm.h.in
+++ b/src/gdbm.h.in
@@ -42,11 +42,12 @@ extern "C" {
# define GDBM_NEWDB 3 /* A writer. Always create a new db. */
# define GDBM_OPENMASK 7 /* Mask for the above. */
-# define GDBM_FAST 0x10 /* Write fast! => No fsyncs. OBSOLETE. */
-# define GDBM_SYNC 0x20 /* Sync operations to the disk. */
-# define GDBM_NOLOCK 0x40 /* Don't do file locking operations. */
-# define GDBM_NOMMAP 0x80 /* Don't use mmap(). */
-
+# define GDBM_FAST 0x010 /* Write fast! => No fsyncs. OBSOLETE. */
+# define GDBM_SYNC 0x020 /* Sync operations to the disk. */
+# define GDBM_NOLOCK 0x040 /* Don't do file locking operations. */
+# define GDBM_NOMMAP 0x080 /* Don't use mmap(). */
+# define GDBM_CLOEXEC 0x100 /* Close the underlying fd on exec(3) */
+
/* Parameters to gdbm_store for simple insertion or replacement in the
case that the key is already in the database. */
# define GDBM_INSERT 0 /* Never replace old data with new. */
@@ -54,7 +55,7 @@ extern "C" {
/* Parameters to gdbm_setopt, specifing the type of operation to perform. */
# define GDBM_SETCACHESIZE 1 /* Set the cache size. */
-# define GDBM_FASTMODE 2 /* Toggle fast mode. OBSOLETE. */
+# define GDBM_FASTMODE 2 /* Toggle fast mode. OBSOLETE. */
# define GDBM_SETSYNCMODE 3 /* Turn on or off sync operations. */
# define GDBM_SETCENTFREE 4 /* Keep all free blocks in the header. */
# define GDBM_SETCOALESCEBLKS 5 /* Attempt to coalesce free blocks. */
@@ -64,8 +65,8 @@ extern "C" {
/* Compatibility defines: */
# define GDBM_CACHESIZE GDBM_SETCACHESIZE
# define GDBM_SYNCMODE GDBM_SETSYNCMODE
-# define GDBM_CENTFREE GDBM_SETCENTFREE
-# define GDBM_COALESCEBLKS GDBM_SETCOALESCEBLKS
+# define GDBM_CENTFREE GDBM_SETCENTFREE
+# define GDBM_COALESCEBLKS GDBM_SETCOALESCEBLKS
# define GDBM_GETFLAGS 8 /* Get gdbm_open flags */
# define GDBM_GETMMAP 9 /* Get mmap status */
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 09eb629..9909d5e 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -64,6 +64,7 @@ gdbm_open (const char *file, int block_size, int flags, int mode,
char need_trunc; /* Used with GDBM_NEWDB and locking to avoid
truncating a file from under a reader. */
int rc; /* temporary error code */
+ int fbits = 0; /* additional bits for open(2) flags */
/* Initialize the gdbm_errno variable. */
gdbm_errno = GDBM_NO_ERROR;
@@ -120,26 +121,27 @@ gdbm_open (const char *file, int block_size, int flags, int mode,
{
dbf->file_locking = FALSE;
}
-
+ if (flags & GDBM_CLOEXEC)
+ fbits = O_CLOEXEC;
/* Open the file. */
need_trunc = FALSE;
switch (flags & GDBM_OPENMASK)
{
case GDBM_READER:
- dbf->desc = open (dbf->name, O_RDONLY, 0);
+ dbf->desc = open (dbf->name, O_RDONLY|fbits, 0);
break;
case GDBM_WRITER:
- dbf->desc = open (dbf->name, O_RDWR, 0);
+ dbf->desc = open (dbf->name, O_RDWR|fbits, 0);
break;
case GDBM_NEWDB:
- dbf->desc = open (dbf->name, O_RDWR|O_CREAT, mode);
+ dbf->desc = open (dbf->name, O_RDWR|O_CREAT|fbits, mode);
need_trunc = TRUE;
break;
default:
- dbf->desc = open (dbf->name, O_RDWR|O_CREAT, mode);
+ dbf->desc = open (dbf->name, O_RDWR|O_CREAT|fbits, mode);
break;
}
diff --git a/src/systems.h b/src/systems.h
index 9a8f449..67b207e 100644
--- a/src/systems.h
+++ b/src/systems.h
@@ -50,6 +50,10 @@
# define L_SET SEEK_SET
#endif
+#ifndef O_CLOEXEC
+# define O_CLOEXEC 0
+#endif
+
/* Default block size. Some systems do not have blocksize in their
stat record. This code uses the BSD blocksize from stat. */

Return to:

Send suggestions and report system problems to the System administrator.