diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | NEWS | 16 | ||||
-rw-r--r-- | compat/dbmopen.c | 42 | ||||
-rw-r--r-- | doc/gdbm.texinfo | 21 | ||||
-rw-r--r-- | src/gdbm.h.in | 17 | ||||
-rw-r--r-- | src/gdbmopen.c | 12 | ||||
-rw-r--r-- | src/systems.h | 4 |
7 files changed, 99 insertions, 30 deletions
@@ -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 @@ -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. */ |