aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS12
-rw-r--r--doc/gdbm.texi21
-rw-r--r--src/gdbm.h.in3
-rw-r--r--src/gdbmconst.h3
-rw-r--r--src/gdbmimp.c8
-rw-r--r--src/gdbmopen.c83
6 files changed, 88 insertions, 42 deletions
diff --git a/NEWS b/NEWS
index 0c0525d..99d4963 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
1GNU dbm NEWS -- history of user-visible changes. 2016-07-13 1GNU dbm NEWS -- history of user-visible changes. 2016-07-15
2Copyright (C) 1990-2016 Free Software Foundation, Inc. 2Copyright (C) 1990-2016 Free Software Foundation, Inc.
3See the end of file for copying conditions. 3See the end of file for copying conditions.
4 4
@@ -23,6 +23,16 @@ Instead it sets gdbm_errno to GDBM_MALLOC_ERROR and returns NULL datum.
23 23
24* Per-database error codes 24* Per-database error codes
25 25
26* New gdbm_open flag: GDBM_BSEXACT
27
28When creating a new database, the gdbm_open function will adjust the
29requested block size so that the block can hold integer number of
30directory entries. Thus, the resulting block size can be bigger than
31the requested one. If the GDBM_BSEXACT flag is set, this behavior is
32suppressed and gdbm_open will try to force exactly the requested block
33size. If unable to do so, it will set the gdbm_errno variable to
34GDBM_BLOCK_SIZE_ERROR and return NULL.
35
26* New functions 36* New functions
27 37
28** gdbm_last_errno 38** gdbm_last_errno
diff --git a/doc/gdbm.texi b/doc/gdbm.texi
index d172ad7..8096215 100644
--- a/doc/gdbm.texi
+++ b/doc/gdbm.texi
@@ -258,9 +258,14 @@ characters to this name).
258It is used during initialization to determine the size of various 258It is used during initialization to determine the size of various
259constructs. It is the size of a single transfer from disk to 259constructs. It is the size of a single transfer from disk to
260memory. This parameter is ignored if the file has been previously 260memory. This parameter is ignored if the file has been previously
261initialized. The minimum size is 512. If the value is less than 512, 261initialized. If the value is less than 512, the file system block
262the file system block size is used, otherwise the value of 262size is used instead. The size is adjusted so that the block can hold
263@var{block_size} is used. 263exact number of directory entries, so that the effective block size
264can be slightly greater than requested. However, if the
265@samp{GDBM_BSEXACT} flag is set and the size needs to be adjusted, the
266function will return with error status, setting the @samp{gdbm_errno}
267variable to @samp{GDBM_BLOCK_SIZE_ERROR}.
268
264@item flags 269@item flags
265@kwindex GDBM_READER 270@kwindex GDBM_READER
266@kwindex GDBM_WRITER 271@kwindex GDBM_WRITER
@@ -287,6 +292,12 @@ from performing any locking on the database file, and @samp{GDBM_NOMMAP},
287which disables the memory mapping mechanism. The option @samp{GDBM_FAST} is 292which disables the memory mapping mechanism. The option @samp{GDBM_FAST} is
288now obsolete, since @code{gdbm} defaults to no-sync mode. 293now obsolete, since @code{gdbm} defaults to no-sync mode.
289 294
295@kwindex GDBM_BSEXACT
296If this flag is set and the requested @var{block_size} cannot be used
297without adjustment, @code{gdbm_open} will refuse to create the
298databases. In this case it will set the @samp{gdbm_errno}
299variable to @samp{GDBM_BLOCK_SIZE_ERROR} and return @samp{NULL}.
300
290@kwindex GDBM_CLOEXEC 301@kwindex GDBM_CLOEXEC
291@cindex close-on-exec 302@cindex close-on-exec
292If the host @samp{open} call 303If the host @samp{open} call
@@ -1233,9 +1244,11 @@ No error occurred.
1233Memory allocation failed. Not enough memory. 1244Memory allocation failed. Not enough memory.
1234 1245
1235@kwindex GDBM_BLOCK_SIZE_ERROR 1246@kwindex GDBM_BLOCK_SIZE_ERROR
1247@kwindex GDBM_BSEXACT
1236@item GDBM_BLOCK_SIZE_ERROR 1248@item GDBM_BLOCK_SIZE_ERROR
1237This error is set by the @code{gdbm_open} function (@pxref{Open}), if 1249This error is set by the @code{gdbm_open} function (@pxref{Open}), if
1238the value of its @var{block_size} argument is incorrect. 1250the value of its @var{block_size} argument is incorrect and the
1251@samp{GDBM_BSEXACT} flag is set.
1239 1252
1240@kwindex GDBM_FILE_OPEN_ERROR 1253@kwindex GDBM_FILE_OPEN_ERROR
1241@item GDBM_FILE_OPEN_ERROR 1254@item GDBM_FILE_OPEN_ERROR
diff --git a/src/gdbm.h.in b/src/gdbm.h.in
index a3d0461..07d3d1f 100644
--- a/src/gdbm.h.in
+++ b/src/gdbm.h.in
@@ -49,6 +49,9 @@ extern "C" {
49# define GDBM_NOLOCK 0x040 /* Don't do file locking operations. */ 49# define GDBM_NOLOCK 0x040 /* Don't do file locking operations. */
50# define GDBM_NOMMAP 0x080 /* Don't use mmap(). */ 50# define GDBM_NOMMAP 0x080 /* Don't use mmap(). */
51# define GDBM_CLOEXEC 0x100 /* Close the underlying fd on exec(3) */ 51# define GDBM_CLOEXEC 0x100 /* Close the underlying fd on exec(3) */
52# define GDBM_BSEXACT 0x200 /* Don't adjust block_size. Bail out with
53 GDBM_BLOCK_SIZE_ERROR error if unable to
54 set it. */
52 55
53/* Parameters to gdbm_store for simple insertion or replacement in the 56/* Parameters to gdbm_store for simple insertion or replacement in the
54 case that the key is already in the database. */ 57 case that the key is already in the database. */
diff --git a/src/gdbmconst.h b/src/gdbmconst.h
index 56820db..66b0fb2 100644
--- a/src/gdbmconst.h
+++ b/src/gdbmconst.h
@@ -38,6 +38,9 @@
38/* Size of a hash value, in bits */ 38/* Size of a hash value, in bits */
39#define GDBM_HASH_BITS 31 39#define GDBM_HASH_BITS 31
40 40
41/* Minimal acceptable block size */
42#define GDBM_MIN_BLOCK_SIZE 512
43
41/* In freeing blocks, we will ignore any blocks smaller (and equal) to 44/* In freeing blocks, we will ignore any blocks smaller (and equal) to
42 IGNORE_SIZE number of bytes. */ 45 IGNORE_SIZE number of bytes. */
43#define IGNORE_SIZE 4 46#define IGNORE_SIZE 4
diff --git a/src/gdbmimp.c b/src/gdbmimp.c
index 57d1933..fc2710d 100644
--- a/src/gdbmimp.c
+++ b/src/gdbmimp.c
@@ -65,14 +65,14 @@ gdbm_import_from_file (GDBM_FILE dbf, FILE *fp, int flag)
65 } 65 }
66 66
67 /* Allocate buffers. */ 67 /* Allocate buffers. */
68 kbufsize = 512; 68 kbufsize = GDBM_MIN_BLOCK_SIZE;
69 kbuffer = malloc (kbufsize); 69 kbuffer = malloc (kbufsize);
70 if (kbuffer == NULL) 70 if (kbuffer == NULL)
71 { 71 {
72 gdbm_set_errno (NULL, GDBM_MALLOC_ERROR, FALSE); 72 gdbm_set_errno (NULL, GDBM_MALLOC_ERROR, FALSE);
73 return -1; 73 return -1;
74 } 74 }
75 dbufsize = 512; 75 dbufsize = GDBM_MIN_BLOCK_SIZE;
76 dbuffer = malloc (dbufsize); 76 dbuffer = malloc (dbufsize);
77 if (dbuffer == NULL) 77 if (dbuffer == NULL)
78 { 78 {
@@ -95,7 +95,7 @@ gdbm_import_from_file (GDBM_FILE dbf, FILE *fp, int flag)
95 95
96 if (size > kbufsize) 96 if (size > kbufsize)
97 { 97 {
98 kbufsize = (size + 512); 98 kbufsize = (size + GDBM_MIN_BLOCK_SIZE);
99 kbuffer = realloc (kbuffer, kbufsize); 99 kbuffer = realloc (kbuffer, kbufsize);
100 if (kbuffer == NULL) 100 if (kbuffer == NULL)
101 { 101 {
@@ -127,7 +127,7 @@ gdbm_import_from_file (GDBM_FILE dbf, FILE *fp, int flag)
127 } 127 }
128 if (size > dbufsize) 128 if (size > dbufsize)
129 { 129 {
130 dbufsize = (size + 512); 130 dbufsize = (size + GDBM_MIN_BLOCK_SIZE);
131 dbuffer = realloc (dbuffer, dbufsize); 131 dbuffer = realloc (dbuffer, dbufsize);
132 if (dbuffer == NULL) 132 if (dbuffer == NULL)
133 { 133 {
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 52814df..5210001 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -31,19 +31,38 @@
31# error "Unsupported off_t size, contact GDBM maintainer. What crazy system is this?!?" 31# error "Unsupported off_t size, contact GDBM maintainer. What crazy system is this?!?"
32#endif 32#endif
33 33
34static void
35compute_directory_size (GDBM_FILE dbf, blksize_t block_size,
36 int *ret_dir_size, int *ret_dir_bits)
37{
38 /* Create the initial hash table directory. */
39 int dir_size = 8 * sizeof (off_t);
40 int dir_bits = 3;
41
42 while (dir_size < block_size && dir_bits < GDBM_HASH_BITS - 3)
43 {
44 dir_size <<= 1;
45 dir_bits++;
46 }
47
48 *ret_dir_size = dir_size;
49 *ret_dir_bits = dir_bits;
50}
51
52
34/* Initialize dbm system. FILE is a pointer to the file name. If the file 53/* Initialize dbm system. FILE is a pointer to the file name. If the file
35 has a size of zero bytes, a file initialization procedure is performed, 54 has a size of zero bytes, a file initialization procedure is performed,
36 setting up the initial structure in the file. BLOCK_SIZE is used during 55 setting up the initial structure in the file. BLOCK_SIZE is used during
37 initialization to determine the size of various constructs. If the value 56 initialization to determine the size of various constructs. If the value
38 is less than 512, the file system blocksize is used, otherwise the value 57 is less than GDBM_MIN_BLOCK_SIZE, the file system blocksize is used,
39 of BLOCK_SIZE is used. BLOCK_SIZE is ignored if the file has previously 58 otherwise the value of BLOCK_SIZE is used. BLOCK_SIZE is ignored if the
40 initialized. If FLAGS is set to GDBM_READ the user wants to just 59 file has previously initialized. If FLAGS is set to GDBM_READ the user
41 read the database and any call to dbm_store or dbm_delete will fail. Many 60 wants to just read the database and any call to dbm_store or dbm_delete
42 readers can access the database at the same time. If FLAGS is set to 61 will fail. Many readers can access the database at the same time. If FLAGS
43 GDBM_WRITE, the user wants both read and write access to the database and 62 is set to GDBM_WRITE, the user wants both read and write access to the
44 requires exclusive access. If FLAGS is GDBM_WRCREAT, the user wants 63 database and requires exclusive access. If FLAGS is GDBM_WRCREAT, the user
45 both read and write access to the database and if the database does not 64 wants both read and write access to the database and if the database does
46 exist, create a new one. If FLAGS is GDBM_NEWDB, the user want a 65 not exist, create a new one. If FLAGS is GDBM_NEWDB, the user want a
47 new database created, regardless of whether one existed, and wants read 66 new database created, regardless of whether one existed, and wants read
48 and write access to the new database. Any error detected will cause a 67 and write access to the new database. Any error detected will cause a
49 return value of null and an approprate value will be in gdbm_errno. If 68 return value of null and an approprate value will be in gdbm_errno. If
@@ -59,7 +78,6 @@ gdbm_open (const char *file, int block_size, int flags, int mode,
59 struct stat file_stat; /* Space for the stat information. */ 78 struct stat file_stat; /* Space for the stat information. */
60 int len; /* Length of the file name. */ 79 int len; /* Length of the file name. */
61 off_t file_pos; /* Used with seeks. */ 80 off_t file_pos; /* Used with seeks. */
62 int file_block_size; /* Block size to use for a new file. */
63 int index; /* Used as a loop index. */ 81 int index; /* Used as a loop index. */
64 char need_trunc; /* Used with GDBM_NEWDB and locking to avoid 82 char need_trunc; /* Used with GDBM_NEWDB and locking to avoid
65 truncating a file from under a reader. */ 83 truncating a file from under a reader. */
@@ -211,18 +229,32 @@ gdbm_open (const char *file, int block_size, int flags, int mode,
211 /* Decide if this is a new file or an old file. */ 229 /* Decide if this is a new file or an old file. */
212 if (file_stat.st_size == 0) 230 if (file_stat.st_size == 0)
213 { 231 {
214
215 /* This is a new file. Create an empty database. */ 232 /* This is a new file. Create an empty database. */
233 int dir_size, dir_bits;
216 234
217 /* Start with the blocksize. */ 235 /* Start with the blocksize. */
218 if (block_size < 512) 236 if (block_size < GDBM_MIN_BLOCK_SIZE)
219 file_block_size = STATBLKSIZE(file_stat); 237 {
238 block_size = STATBLKSIZE (file_stat);