diff options
-rw-r--r-- | NEWS | 12 | ||||
-rw-r--r-- | doc/gdbm.texi | 21 | ||||
-rw-r--r-- | src/gdbm.h.in | 3 | ||||
-rw-r--r-- | src/gdbmconst.h | 3 | ||||
-rw-r--r-- | src/gdbmimp.c | 8 | ||||
-rw-r--r-- | src/gdbmopen.c | 83 |
6 files changed, 88 insertions, 42 deletions
@@ -1,4 +1,4 @@ | |||
1 | GNU dbm NEWS -- history of user-visible changes. 2016-07-13 | 1 | GNU dbm NEWS -- history of user-visible changes. 2016-07-15 |
2 | Copyright (C) 1990-2016 Free Software Foundation, Inc. | 2 | Copyright (C) 1990-2016 Free Software Foundation, Inc. |
3 | See the end of file for copying conditions. | 3 | See 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 | |||
28 | When creating a new database, the gdbm_open function will adjust the | ||
29 | requested block size so that the block can hold integer number of | ||
30 | directory entries. Thus, the resulting block size can be bigger than | ||
31 | the requested one. If the GDBM_BSEXACT flag is set, this behavior is | ||
32 | suppressed and gdbm_open will try to force exactly the requested block | ||
33 | size. If unable to do so, it will set the gdbm_errno variable to | ||
34 | GDBM_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). | |||
258 | It is used during initialization to determine the size of various | 258 | It is used during initialization to determine the size of various |
259 | constructs. It is the size of a single transfer from disk to | 259 | constructs. It is the size of a single transfer from disk to |
260 | memory. This parameter is ignored if the file has been previously | 260 | memory. This parameter is ignored if the file has been previously |
261 | initialized. The minimum size is 512. If the value is less than 512, | 261 | initialized. If the value is less than 512, the file system block |
262 | the file system block size is used, otherwise the value of | 262 | size is used instead. The size is adjusted so that the block can hold |
263 | @var{block_size} is used. | 263 | exact number of directory entries, so that the effective block size |
264 | can be slightly greater than requested. However, if the | ||
265 | @samp{GDBM_BSEXACT} flag is set and the size needs to be adjusted, the | ||
266 | function will return with error status, setting the @samp{gdbm_errno} | ||
267 | variable 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}, | |||
287 | which disables the memory mapping mechanism. The option @samp{GDBM_FAST} is | 292 | which disables the memory mapping mechanism. The option @samp{GDBM_FAST} is |
288 | now obsolete, since @code{gdbm} defaults to no-sync mode. | 293 | now obsolete, since @code{gdbm} defaults to no-sync mode. |
289 | 294 | ||
295 | @kwindex GDBM_BSEXACT | ||
296 | If this flag is set and the requested @var{block_size} cannot be used | ||
297 | without adjustment, @code{gdbm_open} will refuse to create the | ||
298 | databases. In this case it will set the @samp{gdbm_errno} | ||
299 | variable 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 |
292 | If the host @samp{open} call | 303 | If the host @samp{open} call |
@@ -1233,9 +1244,11 @@ No error occurred. | |||
1233 | Memory allocation failed. Not enough memory. | 1244 | Memory 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 |
1237 | This error is set by the @code{gdbm_open} function (@pxref{Open}), if | 1249 | This error is set by the @code{gdbm_open} function (@pxref{Open}), if |
1238 | the value of its @var{block_size} argument is incorrect. | 1250 | the 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 | ||
34 | static void | ||
35 | compute_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); |