/* 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 . */
#ifndef _GDBMEXPORT_
/* Include system configuration before all else. */
# include "autoconf.h"
# include
# 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