diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-11-13 15:28:04 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-11-13 15:28:04 +0000 |
commit | fd714cdcec660f915917edd239324e7544daa234 (patch) | |
tree | 9bcf5029b60bf482a2d13b7b2a2194b4a6f7c6f5 /src | |
parent | 5d14e2acfec6f5ded1c88c7912224157a79be351 (diff) | |
download | gdbm-fd714cdcec660f915917edd239324e7544daa234.tar.gz gdbm-fd714cdcec660f915917edd239324e7544daa234.tar.bz2 |
Implement new dump format. Add new utilities: gdbm_dump and gdbm_load.
* configure.ac (AC_CHECK_HEADERS): Don't check for files that must
always be present. Check for getopt.h.
(AC_CHECK_FUNCS): Add getopt_long
* src/systems.h: Include useless #if's.
* src/flatfile.c: Split into two files:
* src/gdbmexp.c: ... this and ...
* src/gdbmimp.c: .., this
* src/mem.c: New file.
* src/base64.c: New file.
* src/gdbm_dump.c: New file.
* src/gdbm_load.c: New file.
* src/gdbmapp.h: New file.
* src/gdbmdump.c: New file.
* src/gdbmload.c: New file.
* src/parseopt.c: New file.
* src/progname.c: New file.
* src/.cvsignore: Update.
* src/Makefile.am (libgdbm_la_SOURCES): Add new files.
(noinst_LIBRARIES): New variable. Build libgdbmapp.a.
(libgdbmapp_a_SOURCES): New variable.
(bin_PROGRAMS): Add gdbm_load and gdbm_dump
(testgdbm_LDADD, gdbm_load_LDADD)
(gdbm_dump_LDADD): Add ./libgdbmapp.a
* src/gdbm.h.in: Include <stdio.h>
(gdbm_export_to_file)
(gdbm_import_from_file): New prototypes.
(GDBM_DUMP_FMT_BINARY,GDBM_DUMP_FMT_ASCII): New constants.
(gdbm_dump,gdbm_load)
(gdbm_dump_to_file,gdbm_load_from_file): New prototypes.
(GDBM_NO_DBNAME): New error code.
(_GDBM_MAX_ERRNO): Update.
* src/gdbmdefs.h (_GDBM_MAX_DUMP_LINE_LEN): New constant.
* src/gdbmerrno.c (gdbm_errlist): Add entry for GDBM_NO_DBNAME.
* src/proto.h (_gdbm_base64_encode,_gdbm_base64_decode)
(_gdbm_load,_gdbm_dump): New prototypes.
* src/testgdbm.c: Use gdbmapp interface for option parsing.
* export/export.c: Include gdbmexp.c
* export/.cvsignore: Update.
* doc/gdbm.texinfo: Update.
Diffstat (limited to 'src')
-rw-r--r-- | src/.cvsignore | 2 | ||||
-rw-r--r-- | src/Makefile.am | 35 | ||||
-rw-r--r-- | src/base64.c | 127 | ||||
-rw-r--r-- | src/flatfile.c | 246 | ||||
-rw-r--r-- | src/gdbm.h.in | 23 | ||||
-rw-r--r-- | src/gdbm_dump.c | 124 | ||||
-rw-r--r-- | src/gdbm_load.c | 140 | ||||
-rw-r--r-- | src/gdbmapp.h | 52 | ||||
-rw-r--r-- | src/gdbmdefs.h | 2 | ||||
-rw-r--r-- | src/gdbmdump.c | 193 | ||||
-rw-r--r-- | src/gdbmerrno.c | 1 | ||||
-rw-r--r-- | src/gdbmexp.c | 125 | ||||
-rw-r--r-- | src/gdbmimp.c | 157 | ||||
-rw-r--r-- | src/gdbmload.c | 502 | ||||
-rw-r--r-- | src/mem.c | 74 | ||||
-rw-r--r-- | src/parseopt.c | 585 | ||||
-rw-r--r-- | src/progname.c | 35 | ||||
-rw-r--r-- | src/proto.h | 12 | ||||
-rw-r--r-- | src/systems.h | 16 | ||||
-rw-r--r-- | src/testgdbm.c | 142 |
20 files changed, 2233 insertions, 360 deletions
diff --git a/src/.cvsignore b/src/.cvsignore index ee2dbd5..46838d7 100644 --- a/src/.cvsignore +++ b/src/.cvsignore @@ -7,3 +7,5 @@ gdbm.h *.lo libgdbm.la testgdbm +gdbm_dump +gdbm_load diff --git a/src/Makefile.am b/src/Makefile.am index 1c55a4e..2d7a81a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,22 +37,26 @@ lib_LTLIBRARIES = libgdbm.la libgdbm_la_LIBADD = @LTLIBINTL@ libgdbm_la_SOURCES = \ - gdbmopen.c\ - gdbmdelete.c\ - gdbmfetch.c\ - gdbmstore.c\ gdbmclose.c\ - gdbmreorg.c\ - gdbmseq.c\ - gdbmsync.c\ + gdbmdelete.c\ + gdbmdump.c\ gdbmerrno.c\ gdbmexists.c\ + gdbmexp.c\ gdbmfdesc.c\ + gdbmfetch.c\ + gdbmload.c\ + gdbmopen.c\ + gdbmimp.c\ + gdbmreorg.c\ + gdbmseq.c\ gdbmsetopt.c\ + gdbmstore.c\ + gdbmsync.c\ + base64.c\ bucket.c\ falloc.c\ findkey.c\ - flatfile.c\ fullio.c\ hash.c\ lock.c\ @@ -62,6 +66,17 @@ libgdbm_la_SOURCES = \ libgdbm_la_LDFLAGS = -version-info $(VI_CURRENT):$(VI_REVISION):$(VI_AGE) +noinst_LIBRARIES = libgdbmapp.a + +libgdbmapp_a_SOURCES =\ + err.c\ + mem.c\ + gdbmapp.h\ + parseopt.c\ + progname.c + # Programs -bin_PROGRAMS = testgdbm -testgdbm_LDADD = ./libgdbm.la +bin_PROGRAMS = testgdbm gdbm_load gdbm_dump +testgdbm_LDADD = ./libgdbmapp.a ./libgdbm.la +gdbm_load_LDADD = ./libgdbmapp.a ./libgdbm.la +gdbm_dump_LDADD = ./libgdbmapp.a ./libgdbm.la diff --git a/src/base64.c b/src/base64.c new file mode 100644 index 0000000..bf2bf6a --- /dev/null +++ b/src/base64.c @@ -0,0 +1,127 @@ +/* This file is part of GDBM, the GNU data base manager. + Copyright (C) 2011 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 3, 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 "gdbmdefs.h" +# include "gdbm.h" + +static char b64tab[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static int b64val[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 +}; + +int +_gdbm_base64_encode (const unsigned char *input, size_t input_len, + unsigned char **output, size_t *output_size, + size_t *nbytes) +{ + size_t olen = 4 * (input_len + 2) / 3 + 1; + unsigned char *out; + + if (olen > *output_size) + { + out = realloc (*output, olen); + if (!out) + return GDBM_MALLOC_ERROR; + *output = out; + *output_size = olen; + } + else + out = *output; + + while (input_len >= 3) + { + *out++ = b64tab[input[0] >> 2]; + *out++ = b64tab[((input[0] << 4) & 0x30) | (input[1] >> 4)]; + *out++ = b64tab[((input[1] << 2) & 0x3c) | (input[2] >> 6)]; + *out++ = b64tab[input[2] & 0x3f]; + input_len -= 3; + input += 3; + } + + if (input_len > 0) + { + unsigned char c = (input[0] << 4) & 0x30; + *out++ = b64tab[input[0] >> 2]; + if (input_len > 1) + c |= input[1] >> 4; + *out++ = b64tab[c]; + *out++ = (input_len < 2) ? '=' : b64tab[(input[1] << 2) & 0x3c]; + *out++ = '='; + } + *out = 0; + *nbytes = out - *output; + return 0; +} + +int +_gdbm_base64_decode (const unsigned char *input, size_t input_len, + unsigned char **output, size_t *output_size, + size_t *inbytes, size_t *outbytes) +{ + int rc = 0; + int olen = input_len; + unsigned char *out; + size_t ins = 0; + + if (olen > *output_size) + { + out = realloc (*output, olen); + if (!out) + return GDBM_MALLOC_ERROR; + *output = out; + *output_size = olen; + } + else + out = *output; + + do + { + if (input_len < 4) + break; + if (input[0] > 127 || b64val[input[0]] == -1 + || input[1] > 127 || b64val[input[1]] == -1 + || input[2] > 127 || ((input[2] != '=') && (b64val[input[2]] == -1)) + || input[3] > 127 || ((input[3] != '=') + && (b64val[input[3]] == -1))) + { + rc = GDBM_ILLEGAL_DATA; + break; + } + *out++ = (b64val[input[0]] << 2) | (b64val[input[1]] >> 4); + if (input[2] != '=') + { + *out++ = ((b64val[input[1]] << 4) & 0xf0) | (b64val[input[2]] >> 2); + if (input[3] != '=') + *out++ = ((b64val[input[2]] << 6) & 0xc0) | b64val[input[3]]; + } + input += 4; + input_len -= 4; + ins += 4; + } + while (input_len > 0); + *inbytes = ins; + *outbytes = out - *output; + return rc; +} diff --git a/src/flatfile.c b/src/flatfile.c deleted file mode 100644 index c0f9422..0000000 --- a/src/flatfile.c +++ /dev/null @@ -1,246 +0,0 @@ -/* flatfile.c - Import/export a GDBM database. */ - -/* This file is part of GDBM, the GNU data base manager. - Copyright (C) 2007, 2011 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 3, 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/>. */ - -#ifndef _GDBMEXPORT_ - -/* Include system configuration before all else. */ -# include "autoconf.h" -# include <arpa/inet.h> - -# include "gdbmdefs.h" -# include "gdbm.h" - -#endif - -int -gdbm_export (GDBM_FILE dbf, const char *exportfile, int flags, int mode) -{ - int nfd, size; - datum key, nextkey, data; - const char *header1 = "!\r\n! GDBM FLAT FILE DUMP -- THIS IS NOT A TEXT FILE\r\n! "; - const char *header2 = "\r\n!\r\n"; - int count = 0; - - /* Only support GDBM_WCREAT or GDBM_NEWDB */ - switch (flags) - { - case GDBM_WRCREAT: - nfd = open (exportfile, O_WRONLY | O_CREAT | O_EXCL, mode); - if (nfd == -1) - { - gdbm_errno = GDBM_FILE_OPEN_ERROR; - return -1; - } - break; - case GDBM_NEWDB: - nfd = open (exportfile, O_WRONLY | O_CREAT | O_TRUNC, mode); - if (nfd == -1) - { - gdbm_errno = GDBM_FILE_OPEN_ERROR; - return -1; - } - break; - default: -#ifdef GDBM_BAD_OPEN_FLAGS - gdbm_errno = GDBM_BAD_OPEN_FLAGS; -#else - gdbm_errno = GDBM_FILE_OPEN_ERROR; -#endif - return -1; - } - - /* Write out the text header. */ - if (write (nfd, header1, strlen (header1)) != strlen (header1)) - goto write_fail; - if (write (nfd, gdbm_version, strlen (gdbm_version)) != strlen (gdbm_version)) - goto write_fail; - if (write (nfd, header2, strlen (header2)) != strlen (header2)) - goto write_fail; - - /* For each item in the database, write out a record to the file. */ - key = gdbm_firstkey (dbf); - - while (key.dptr != NULL) - { - data = gdbm_fetch (dbf, key); - if (data.dptr != NULL) - { - /* Add the data to the new file. */ - size = htonl (key.dsize); - if (write (nfd, &size, sizeof(int)) != sizeof (int)) - goto write_fail; - if (write (nfd, key.dptr, key.dsize) != key.dsize) - goto write_fail; - - size = htonl (data.dsize); - if (write (nfd, &size, sizeof(int)) != sizeof (int)) - goto write_fail; - if (write (nfd, data.dptr, data.dsize) != data.dsize) - goto write_fail; - } - nextkey = gdbm_nextkey (dbf, key); - free (key.dptr); - free (data.dptr); - key = nextkey; - - count++; - } - close (nfd); - - return count; - - write_fail: - - gdbm_errno = GDBM_FILE_WRITE_ERROR; - return -1; -} - -#ifndef _GDBMEXPORT_ - -int -gdbm_import (GDBM_FILE dbf, const char *importfile, int flag) -{ - int ifd, seenbang, seennewline, rsize, size, kbufsize, dbufsize, rret; - char c, *kbuffer, *dbuffer; - datum key, data; - int count = 0; - - ifd = open (importfile, O_RDONLY, 0); - if (ifd == -1) - { - gdbm_errno = GDBM_FILE_OPEN_ERROR; - return -1; - } - - seenbang = 0; - seennewline = 0; - kbuffer = NULL; - dbuffer = NULL; - - /* Read (and discard) four lines begining with ! and ending with \n. */ - while (1) - { - if (read (ifd, &c, 1) != 1) - goto read_fail; - - if (c == '!') - seenbang++; - if (c == '\n') - { - if (seenbang > 3 && seennewline > 2) - { - /* End of last line. */ - break; - } - seennewline++; - } - } - - /* Allocate buffers. */ - kbufsize = 512; - kbuffer = malloc (kbufsize); - if (kbuffer == NULL) - { - gdbm_errno = GDBM_MALLOC_ERROR; - close (ifd); - return -1; - } - dbufsize = 512; - dbuffer = malloc (dbufsize); - if (dbuffer == NULL) - { - gdbm_errno = GDBM_MALLOC_ERROR; - close (ifd); - return -1; - } - - /* Insert/replace records in the database until we run out of file. */ - while ((rret = read (ifd, &rsize, sizeof(rsize))) != 0) - { - if (rret != sizeof(rsize)) - goto read_fail; - - /* Read the key. */ - size = ntohl (rsize); - if (size > kbufsize) - { - kbufsize = (size + 512); - kbuffer = realloc (kbuffer, kbufsize); - if (kbuffer == NULL) - { - gdbm_errno = GDBM_MALLOC_ERROR; - close (ifd); - return -1; - } - } - if (read (ifd, kbuffer, size) != size) - goto read_fail; - - key.dptr = kbuffer; - key.dsize = size; - - /* Read the data. */ - if (read (ifd, &rsize, sizeof(rsize)) != sizeof(rsize)) - goto read_fail; - - size = ntohl (rsize); - if (size > dbufsize) - { - dbufsize = (size + 512); - dbuffer = realloc (dbuffer, dbufsize); - if (dbuffer == NULL) - { - gdbm_errno = GDBM_MALLOC_ERROR; - close (ifd); - return -1; - } - } - if (read (ifd, dbuffer, size) != size) - goto read_fail; - - data.dptr = dbuffer; - data.dsize = size; - - if (gdbm_store (dbf, key, data, flag) != 0) - { - /* Keep the existing errno. */ - free (kbuffer); - free (dbuffer); - close (ifd); - return -1; - } - - count++; - } - - close (ifd); - return count; - -read_fail: - - if (kbuffer != NULL) - free (kbuffer); - if (dbuffer != NULL) - free (dbuffer); - - close (ifd); - - gdbm_errno = GDBM_FILE_READ_ERROR; - return -1; -} -#endif diff --git a/src/gdbm.h.in b/src/gdbm.h.in index 21168de..81e9943 100644 --- a/src/gdbm.h.in +++ b/src/gdbm.h.in @@ -29,6 +29,8 @@ #ifndef _GDBM_H_ # define _GDBM_H_ +# include <stdio.h> + /* GDBM C++ support */ # if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -111,8 +113,24 @@ extern void 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); + extern int gdbm_export (GDBM_FILE, const char *, int, int); +extern int gdbm_export_to_file (GDBM_FILE dbf, FILE *fp); + extern int gdbm_import (GDBM_FILE, const char *, int); +extern int gdbm_import_from_file (GDBM_FILE dbf, FILE *fp, int flag); + +#define GDBM_DUMP_FMT_BINARY 0 +#define GDBM_DUMP_FMT_ASCII 1 + +extern int gdbm_dump (GDBM_FILE, const char *, int fmt, int open_flags, + int mode); +extern int gdbm_dump_to_file (GDBM_FILE, FILE *, int fmt); + +extern int gdbm_load (GDBM_FILE *, const char *, int replace, + unsigned long *line); +extern int gdbm_load_from_file (GDBM_FILE *, FILE *, int replace, + unsigned long *line); # define GDBM_NO_ERROR 0 # define GDBM_MALLOC_ERROR 1 @@ -140,9 +158,10 @@ extern int gdbm_import (GDBM_FILE, const char *, int); # define GDBM_BAD_OPEN_FLAGS 23 # define GDBM_FILE_STAT_ERROR 24 # define GDBM_FILE_EOF 25 - +# define GDBM_NO_DBNAME 26 + # define _GDBM_MIN_ERRNO 0 -# define _GDBM_MAX_ERRNO GDBM_FILE_EOF +# define _GDBM_MAX_ERRNO GDBM_NO_DBNAME typedef int gdbm_error; /* For compatibilities sake. */ extern gdbm_error gdbm_errno; extern const char * const gdbm_errlist[]; diff --git a/src/gdbm_dump.c b/src/gdbm_dump.c new file mode 100644 index 0000000..6ea94e6 --- /dev/null +++ b/src/gdbm_dump.c @@ -0,0 +1,124 @@ +/* This file is part of GDBM, the GNU data base manager. + Copyright (C) 2011 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 3, 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 "gdbm.h" +# include "gdbmapp.h" +# include "gdbmdefs.h" + +char *parseopt_program_doc = "dump a GDBM database to a file"; +char *parseopt_program_args = "DB_FILE [FILE]"; +struct gdbm_option optab[] = { + { 'H', "format", N_("0|1"), N_("select dump format") }, + { 'b', "binary", NULL, N_("use binary output format") }, + { 0 } +}; + +int format = GDBM_DUMP_FMT_ASCII; + +int +main (int argc, char **argv) +{ + GDBM_FILE dbf; + int rc, opt; + char *dbname, *filename; + FILE *fp; + + set_progname (argv[0]); + + for (opt = parseopt_first (argc, argv, optab); + opt != EOF; + opt = parseopt_next ()) + { + switch (opt) + { + case 'b': + format = GDBM_DUMP_FMT_BINARY; + break; + + case 'H': + format = atoi (optarg); + switch (format) + { + case GDBM_DUMP_FMT_BINARY: + case GDBM_DUMP_FMT_ASCII: + break; + default: + error (_("unknown dump format")); + exit (2); + } + break; + + default: + error (_("unknown option")); + exit (2); + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) + { + parseopt_print_help (); + exit (0); + } + + if (argc > 2) + { + error (_("too many arguments; try `%s -h' for more info"), progname); + exit (2); + } + + dbname = argv[0]; + if (argc == 2) + filename = argv[1]; + else + filename = NULL; + + if (!filename || strcmp (filename, "-") == 0) + { + filename = "<stdout>"; + fp = stdout; + } + else + { + fp = fopen (filename, "w"); + if (!fp) + { + sys_perror (errno, _("cannot open %s"), filename); + exit (1); + } + } + + dbf = gdbm_open (dbname, 0, GDBM_READER, 0600, NULL); + if (!dbf) + { + gdbm_perror (_("gdbm_open failed")); + exit (1); + } + + rc = gdbm_dump_to_file (dbf, fp, format); + if (rc) + { + gdbm_perror (_("dump error"), filename); + } + + gdbm_close (dbf); + + exit (!!rc); +} + diff --git a/src/gdbm_load.c b/src/gdbm_load.c new file mode 100644 index 0000000..4e14207 --- /dev/null +++ b/src/gdbm_load.c @@ -0,0 +1,140 @@ +/* This file is part of GDBM, the GNU data base manager. + Copyright (C) 2011 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 3, 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 "gdbm.h" +# include "gdbmapp.h" +# include "gdbmdefs.h" + +/* usage: gdbm_load [OPTIONS] FILE [DB_FILE] + FILE is either "-" or a file name. + OPTIONS are: + -h, --help + -u, --usage + -v, --version + + -p, --permissions OOO + -u, --user NAME-OR-UID + -g, --group NAME-OR-GID +*/ + +int replace = 0; + +char *parseopt_program_doc = "load a GDBM database from a file"; +char *parseopt_program_args = "FILE [DB_FILE]"; +struct gdbm_option optab[] = { + { 'r', "replace", NULL, N_("replace records in the existing database") }, + { 0 } +}; + +int +main (int argc, char **argv) +{ + GDBM_FILE dbf = NULL; + int rc, opt; + char *dbname, *filename; + FILE *fp; + unsigned long err_line; + + set_progname (argv[0]); + + for (opt = parseopt_first (argc, argv, optab); + opt != EOF; + opt = parseopt_next ()) + { + switch (opt) + { + case 'r': + replace = 1; + break; + + default: + error (_("unknown option")); + exit (2); + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) + { + parseopt_print_help (); + exit (0); + } + + if (argc > 2) + { + error (_("too many arguments; try `%s -h' for more info"), progname); + exit (2); + } + + filename = argv[0]; + if (argc == 2) + dbname = argv[1]; + else + dbname = NULL; + + if (strcmp (filename, "-") == 0) + { + filename = "<stdin>"; + fp = stdin; + } + else + { + fp = fopen (filename, "r"); + if (!fp) + { + sys_perror (errno, _("cannot open %s"), filename); + exit (1); + } + } + + if (dbname) + { + dbf = gdbm_open (dbname, 0, GDBM_NEWDB, 0600, NULL); + if (!dbf) + { + gdbm_perror (_("gdbm_open failed")); + exit (1); + } + } + + rc = gdbm_load_from_file (&dbf, fp, replace, &err_line); + if (rc) + { + if (err_line) + gdbm_perror ("%s:%lu", filename, err_line); + else + gdbm_perror ("cannot load from %s", filename); + } + + if (dbf) + { + if (!dbname) + { + if (gdbm_setopt (dbf, GDBM_GETDBNAME, &dbname, sizeof (dbname))) + gdbm_perror (_("gdbm_setopt failed")); + else + { + printf ("%s: created %s\n", progname, dbname); + free (dbname); + } + } + gdbm_close (dbf); + } + exit (!!rc); +} diff --git a/src/gdbmapp.h b/src/gdbmapp.h new file mode 100644 index 0000000..e7917f9 --- /dev/null +++ b/src/gdbmapp.h @@ -0,0 +1,52 @@ +/* This file is part of GDBM, the GNU data base manager. + Copyright (C) 2011 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 3, 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 <stdlib.h> +#include <stdarg.h> + +extern const char *progname; + +void set_progname (const char *arg); +void gdbm_perror (const char *fmt, ...); +void sys_perror (int code, const char *fmt, ...); +void error (const char *fmt, ...); +void verror (const char *fmt, va_list ap); + +void *emalloc (size_t size); +void *erealloc (void *ptr, size_t size); +void *ecalloc (size_t nmemb, size_t size); +void *ezalloc (size_t size); +char *estrdup (char *str); + +#define PARSEOPT_HIDDEN 0x01 +#define PARSEOPT_ALIAS 0x02 + +struct gdbm_option +{ + int opt_short; + char *opt_long; + char *opt_arg; + char *opt_descr; + int opt_flags; +}; + +int parseopt_first (int pc, char **pv, struct gdbm_option *options); +int parseopt_next (void); +void parseopt_print_help (void); + +extern char *parseopt_program_name; +extern char *parseopt_program_doc; +extern char *parseopt_program_args; diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h index 519d688..4ebb190 100644 --- a/src/gdbmdefs.h +++ b/src/gdbmdefs.h @@ -217,5 +217,7 @@ struct gdbm_file_info { } \ while (0) \ +#define _GDBM_MAX_DUMP_LINE_LEN 76 + /* Now define all the routines in use. */ #include "proto.h" diff --git a/src/gdbmdump.c b/src/gdbmdump.c new file mode 100644 index 0000000..9380931 --- /dev/null +++ b/src/gdbmdump.c @@ -0,0 +1,193 @@ +/* This file is part of GDBM, the GNU data base manager. + Copyright (C) 2011 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 3, 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 "gdbmdefs.h" +# include "gdbm.h" +# include <pwd.h> +# include <grp.h> +# include <time.h> + +static int +print_datum (datum const *dat, unsigned char **bufptr, + size_t *bufsize, FILE *fp) +{ + int rc; + size_t len; + unsigned char *p; + + fprintf (fp, "#:len=%lu\n", (unsigned long) dat->dsize); + rc = _gdbm_base64_encode ((unsigned char*) dat->dptr, dat->dsize, + bufptr, bufsize, &len); + if (rc) + return rc; + + p = *bufptr; + while (len) + { + size_t n = len; + if (n > _GDBM_MAX_DUMP_LINE_LEN) + n = _GDBM_MAX_DUMP_LINE_LEN; + if (fwrite (p, n, 1, fp) != 1) + return GDBM_FILE_WRITE_ERROR; + fputc ('\n', fp); + len -= n; + p += n; + } + return 0; +} + +int +_gdbm_dump_ascii (GDBM_FILE dbf, FILE *fp) +{ + time_t t; + int fd; + struct stat st; + struct passwd *pw; + struct group *gr; + datum key; + size_t count = 0; + unsigned char *buffer = NULL; + size_t bufsize = 0; + int rc; + + fd = gdbm_fdesc (dbf); + if (fstat (fd, &st)) + return GDBM_FILE_STAT_ERROR; + + /* Print header */ + time (&t); + fprintf (fp, "# GDBM dump file created by %s on %s", + gdbm_version, ctime (&t)); + fprintf (fp, "#:version=1.0\n"); + + fprintf (fp, "#:file=%s\n", dbf->name); + fprintf (fp, "#:uid=%lu,", (unsigned long) st.st_uid); + pw = getpwuid (st.st_uid); + if (pw) + fprintf (fp, "user=%s,", pw->pw_name); + fprintf (fp, "gid=%lu,", (unsigned long) st.st_gid); + gr = getgrgid (st.st_gid); + if (gr) + fprintf (fp, "group=%s,", gr->gr_name); + fprintf (fp, "mode=%03o\n", st.st_mode & 0777); + fprintf (fp, "# End of header\n"); + + key = gdbm_firstkey (dbf); + + while (key.dptr) + { + datum nextkey; + datum data = gdbm_fetch (dbf, key); + if (data.dptr) + { + if ((rc = print_datum (&key, &buffer, &bufsize, fp)) || + (rc = print_datum (&data, &buffer, &bufsize, fp))) + { + free (key.dptr); + free (data.dptr); + gdbm_errno = rc; + break; + } + } + nextkey = gdbm_nextkey (dbf, key); + free (key.dptr); + free (data.dptr); + key = nextkey; + count++; + } + + if (rc == 0) + { + /* FIXME: Something like that won't hurt, although load does not + use it currently. */ + fprintf (fp, "#:count=%lu\n", (unsigned long) count); + fprintf (fp, "# End of data\n"); + } + free (buffer); + + if (ferror(fp)) + rc = gdbm_errno = GDBM_FILE_WRITE_ERROR; + + return rc ? -1 : 0; +} + +int +gdbm_dump_to_file (GDBM_FILE dbf, FILE *fp, int format) +{ + int rc; + + switch (format) + { + case GDBM_DUMP_FMT_BINARY: + rc = gdbm_export_to_file (dbf, fp) == -1; + break; + + case GDBM_DUMP_FMT_ASCII: + rc = _gdbm_dump_ascii (dbf, fp); + break; + + default: + return EINVAL; + } + return rc; +} + +int +gdbm_dump (GDBM_FILE dbf, const char *filename, int fmt, int open_flags, + int mode) +{ + int nfd, rc; + FILE *fp; + + /* Only support GDBM_WCREAT or GDBM_NEWDB */ + switch (open_flags) + { + case GDBM_WRCREAT: + nfd = open (filename, O_WRONLY | O_CREAT | O_EXCL, mode); + if (nfd == -1) + { + gdbm_errno = GDBM_FILE_OPEN_ERROR; + return -1; + } + break; + case GDBM_NEWDB: + nfd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, mode); + if (nfd == -1) + { + gdbm_errno = GDBM_FILE_OPEN_ERROR; + return -1; + } + break; + default: + gdbm_errno = GDBM_BAD_OPEN_FLAGS; + return -1; + } + + fp = fdopen (nfd, "w"); + if (!fp) + { + close (nfd); + gdbm_errno = GDBM_FILE_OPEN_ERROR; + return -1; + } + rc = gdbm_dump_to_file (dbf, fp, fmt); + fclose (fp); + return rc; +} + + + diff --git a/src/gdbmerrno.c b/src/gdbmerrno.c index d9c5c3f..de1aab7 100644 --- a/src/gdbmerrno.c +++ b/src/gdbmerrno.c @@ -54,6 +54,7 @@ const char * const gdbm_errlist[_GDBM_MAX_ERRNO+1] = { |