diff options
author | Jason Downs <downsj@downsj.com> | 2008-11-21 21:33:39 +0000 |
---|---|---|
committer | Jason Downs <downsj@downsj.com> | 2008-11-21 21:33:39 +0000 |
commit | 10fe387708ddfba6449b9abd74cfbdf67d495465 (patch) | |
tree | 50115c0708c762940f580d081c73495bf148101a /src/flatfile.c | |
download | gdbm-10fe387708ddfba6449b9abd74cfbdf67d495465.tar.gz gdbm-10fe387708ddfba6449b9abd74cfbdf67d495465.tar.bz2 |
Initial revision
Diffstat (limited to 'src/flatfile.c')
-rw-r--r-- | src/flatfile.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/src/flatfile.c b/src/flatfile.c new file mode 100644 index 0000000..4d182d8 --- /dev/null +++ b/src/flatfile.c @@ -0,0 +1,250 @@ +/* flatfile.c - Import/export a GDBM database. */ + +/* This file is part of GDBM, the GNU data base manager. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program 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. + + This program 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 this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _GDBMEXPORT_ + +/* Include system configuration before all else. */ +#include "autoconf.h" + +#include "gdbmdefs.h" +#include "gdbmerrno.h" +#include "extern.h" + +extern const char * gdbm_version; + +int +gdbm_export (gdbm_file_info *dbf, const char *exportfile, int flags, int mode) +#else +int +gdbm_export (GDBM_FILE dbf, const char *exportfile, int flags, int mode) +#endif +{ + 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_info *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 |