summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormichael <michael@82007160-df01-0410-b94d-b575c5fd34c7>2012-10-31 22:54:58 +0000
committermichael <michael@82007160-df01-0410-b94d-b575c5fd34c7>2012-10-31 22:54:58 +0000
commit67759eb6e3fc0c1aaa41ae8b6dee559eb428936f (patch)
tree7942bd514b12fb30d47339dcf4d259a519aee97e /src
parente33fb1d4ccaed39a453edf329c6649155a9ac1e4 (diff)
- Added conf_db.c based on ircservice's binary database for later use
git-svn-id: svn://svn.ircd-hybrid.org/svnroot/ircd-hybrid/trunk@1620 82007160-df01-0410-b94d-b575c5fd34c7
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile.in35
-rw-r--r--src/conf_db.c599
3 files changed, 619 insertions, 16 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2f51356..08ccec6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,6 +14,7 @@ ircd_SOURCES = balloc.c \
channel_mode.c \
client.c \
conf.c \
+ conf_db.c \
conf_parser.y \
conf_lexer.l \
csvlib.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index a8102c7..1343ee8 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -68,22 +68,23 @@ am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS)
am_ircd_OBJECTS = balloc.$(OBJEXT) channel.$(OBJEXT) \
channel_mode.$(OBJEXT) client.$(OBJEXT) conf.$(OBJEXT) \
- conf_parser.$(OBJEXT) conf_lexer.$(OBJEXT) csvlib.$(OBJEXT) \
- dbuf.$(OBJEXT) event.$(OBJEXT) fdlist.$(OBJEXT) \
- getopt.$(OBJEXT) hash.$(OBJEXT) hook.$(OBJEXT) \
- hostmask.$(OBJEXT) irc_res.$(OBJEXT) irc_reslib.$(OBJEXT) \
- irc_string.$(OBJEXT) ircd.$(OBJEXT) ircd_signal.$(OBJEXT) \
- list.$(OBJEXT) listener.$(OBJEXT) log.$(OBJEXT) \
- match.$(OBJEXT) memory.$(OBJEXT) modules.$(OBJEXT) \
- motd.$(OBJEXT) rng_mt.$(OBJEXT) numeric.$(OBJEXT) \
- packet.$(OBJEXT) parse.$(OBJEXT) s_bsd_epoll.$(OBJEXT) \
- s_bsd_poll.$(OBJEXT) s_bsd_sigio.$(OBJEXT) \
- s_bsd_devpoll.$(OBJEXT) s_bsd_kqueue.$(OBJEXT) \
- s_bsd_select.$(OBJEXT) restart.$(OBJEXT) resv.$(OBJEXT) \
- rsa.$(OBJEXT) s_auth.$(OBJEXT) s_bsd.$(OBJEXT) \
- s_gline.$(OBJEXT) s_misc.$(OBJEXT) s_serv.$(OBJEXT) \
- s_user.$(OBJEXT) send.$(OBJEXT) sprintf_irc.$(OBJEXT) \
- version.$(OBJEXT) watch.$(OBJEXT) whowas.$(OBJEXT)
+ conf_db.$(OBJEXT) conf_parser.$(OBJEXT) conf_lexer.$(OBJEXT) \
+ csvlib.$(OBJEXT) dbuf.$(OBJEXT) event.$(OBJEXT) \
+ fdlist.$(OBJEXT) getopt.$(OBJEXT) hash.$(OBJEXT) \
+ hook.$(OBJEXT) hostmask.$(OBJEXT) irc_res.$(OBJEXT) \
+ irc_reslib.$(OBJEXT) irc_string.$(OBJEXT) ircd.$(OBJEXT) \
+ ircd_signal.$(OBJEXT) list.$(OBJEXT) listener.$(OBJEXT) \
+ log.$(OBJEXT) match.$(OBJEXT) memory.$(OBJEXT) \
+ modules.$(OBJEXT) motd.$(OBJEXT) rng_mt.$(OBJEXT) \
+ numeric.$(OBJEXT) packet.$(OBJEXT) parse.$(OBJEXT) \
+ s_bsd_epoll.$(OBJEXT) s_bsd_poll.$(OBJEXT) \
+ s_bsd_sigio.$(OBJEXT) s_bsd_devpoll.$(OBJEXT) \
+ s_bsd_kqueue.$(OBJEXT) s_bsd_select.$(OBJEXT) \
+ restart.$(OBJEXT) resv.$(OBJEXT) rsa.$(OBJEXT) \
+ s_auth.$(OBJEXT) s_bsd.$(OBJEXT) s_gline.$(OBJEXT) \
+ s_misc.$(OBJEXT) s_serv.$(OBJEXT) s_user.$(OBJEXT) \
+ send.$(OBJEXT) sprintf_irc.$(OBJEXT) version.$(OBJEXT) \
+ watch.$(OBJEXT) whowas.$(OBJEXT)
ircd_OBJECTS = $(am_ircd_OBJECTS)
am__DEPENDENCIES_1 =
ircd_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -274,6 +275,7 @@ ircd_SOURCES = balloc.c \
channel_mode.c \
client.c \
conf.c \
+ conf_db.c \
conf_parser.y \
conf_lexer.l \
csvlib.c \
@@ -419,6 +421,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel_mode.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf_db.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf_lexer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf_parser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csvlib.Po@am__quote@
diff --git a/src/conf_db.c b/src/conf_db.c
new file mode 100644
index 0000000..8092a9c
--- /dev/null
+++ b/src/conf_db.c
@@ -0,0 +1,599 @@
+/*
+ * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ *
+ * Copyright (C) 1996-2002 by Andrew Church <achurch@achurch.org>
+ * Copyright (C) 2012 by the Hybrid Development Team.
+ *
+ * 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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*! \file conf_db.c
+ * \brief Includes file utilities for database handling
+ * \version $Id: conf_db.c 1569 2012-10-16 18:46:53Z michael $
+ */
+
+#include "stdinc.h"
+#include "conf_db.h"
+#include "memory.h"
+#include "client.h"
+#include "log.h"
+#include "send.h"
+#include "irc_string.h"
+
+
+/*! \brief Return the version number on the file. Return 0 if there is no version
+ * number or the number doesn't make sense (i.e. less than 1 or greater
+ * than FILE_VERSION).
+ *
+ * \param f dbFile Struct Member
+ * \return int 0 if failure, 1 > is the version number
+ */
+int
+get_file_version(struct dbFILE *f)
+{
+ FILE *fp = f->fp;
+ int version = fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp);
+
+ if (ferror(fp))
+ {
+ ilog(LOG_TYPE_IRCD, "Error reading version number on %s", f->filename);
+ return 0;
+ }
+ else if (feof(fp))
+ {
+ ilog(LOG_TYPE_IRCD, "Error reading version number on %s: End of file detected",
+ f->filename);
+ return 0;
+ }
+ else if (version < 1)
+ {
+ ilog(LOG_TYPE_IRCD, "Invalid version number (%d) on %s",
+ version, f->filename);
+ return 0;
+ }
+
+ return version;
+}
+
+/*! \brief Write the current version number to the file.
+ * \param f dbFile Struct Member
+ * \return 0 on error, 1 on success.
+ */
+int
+write_file_version(struct dbFILE *f, uint32_t version)
+{
+ if (write_uint32(version, f) == -1)
+ {
+ ilog(LOG_TYPE_IRCD, "Error writing version number on %s",
+ f->filename);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*! \brief Open the database for reading
+ * \param service If error whom to return the error as
+ * \param filename File to open as the database
+ * \return dbFile struct
+ */
+static struct dbFILE *
+open_db_read(const char *service, const char *filename)
+{
+ struct dbFILE *f = MyMalloc(sizeof(*f));
+ FILE *fp = NULL;
+
+ strlcpy(f->filename, filename, sizeof(f->filename));
+
+ f->mode = 'r';
+ fp = fopen(f->filename, "rb");
+
+ if (!fp)
+ {
+ int errno_save = errno;
+
+ if (errno != ENOENT)
+ ilog(LOG_TYPE_IRCD, "Can not read %s database %s", service,
+ f->filename);
+
+ MyFree(f);
+ errno = errno_save;
+ return NULL;
+ }
+
+ f->fp = fp;
+ f->backupfp = NULL;
+
+ return f;
+}
+
+/*! \brief Open the database for writting
+ * \param service If error whom to return the error as
+ * \param filename File to open as the database
+ * \param version Database Version
+ * \return dbFile struct
+ */
+static struct dbFILE *
+open_db_write(const char *service, const char *filename,
+ uint32_t version)
+{
+ struct dbFILE *f = MyMalloc(sizeof(*f));
+ int fd = 0;
+
+ strlcpy(f->filename, filename, sizeof(f->filename));
+
+ filename = f->filename;
+ f->mode = 'w';
+
+ snprintf(f->backupname, sizeof(f->backupname), "%s.save", filename);
+
+ if (!*f->backupname || !strcmp(f->backupname, filename))
+ {
+ int errno_save = errno;
+
+ ilog(LOG_TYPE_IRCD, "Opening %s database %s for write: Filename too long",
+ service, filename);
+ MyFree(f);
+ errno = errno_save;
+ return NULL;
+ }
+
+ unlink(filename);
+
+ f->backupfp = fopen(filename, "rb");
+
+ if (rename(filename, f->backupname) < 0 && errno != ENOENT)
+ {
+ int errno_save = errno;
+ static int walloped = 0;
+
+ if (!walloped++)
+ sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
+ "Can not back up %s database %s",
+ service, filename);
+
+ errno = errno_save;
+ ilog(LOG_TYPE_IRCD, "Can not back up %s database %s", service, filename);
+
+ if (f->backupfp)
+ fclose(f->backupfp);
+
+ MyFree(f);
+ errno = errno_save;
+ return NULL;
+ }
+
+ unlink(filename);
+
+ /* Use open() to avoid people sneaking a new file in under us */
+ fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
+ f->fp = fdopen(fd, "wb"); /* will fail and return NULL if fd < 0 */
+
+ if (!f->fp || !write_file_version(f, version))
+ {
+ int errno_save = errno;
+ static int walloped = 0;
+
+ if (!walloped++)
+ sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
+ "Can't write to %s database %s",
+ service, filename);
+
+ errno = errno_save;
+ ilog(LOG_TYPE_IRCD, "Can't write to %s database %s",
+ service, filename);
+
+ if (f->fp)
+ {
+ fclose(f->fp);
+ unlink(filename);
+ }
+
+ if (f->backupname[0] && rename(f->backupname, filename) < 0)
+ ilog(LOG_TYPE_IRCD, "Cannot restore backup copy of %s",
+ filename);
+
+ MyFree(f);
+ errno = errno_save;
+ return NULL;
+ }
+
+ return f;
+}
+
+/*! \brief Open a database file for reading (*mode == 'r') or writing (*mode == 'w').
+ * Return the stream pointer, or NULL on error. When opening for write, it
+ * is an error for rename() to return an error (when backing up the original
+ * file) other than ENOENT, if NO_BACKUP_OKAY is not defined; it is an error
+ * if the version number cannot be written to the file; and it is a fatal
+ * error if opening the file for write fails and the backup was successfully
+ * made but cannot be restored.
+ *
+ * \param service If error whom to return the error as
+ * \param filename File to open as the database
+ * \param mode Mode for writting or reading
+ * \param version Database Version
+ * \return dbFile struct
+ */
+struct dbFILE *
+open_db(const char *service, const char *filename,
+ const char *mode, uint32_t version)
+{
+ switch (*mode)
+ {
+ case 'r':
+ return open_db_read(service, filename);
+ break;
+ case 'w':
+ return open_db_write(service, filename, version);
+ break;
+ default:
+ errno = EINVAL;
+ return NULL;
+ }
+}
+
+/*! \brief Restore the database file to its condition before open_db(). This is
+ * identical to close_db() for files open for reading; however, for files
+ * open for writing, we first attempt to restore any backup file before
+ * closing files.
+ *
+ * \param dbFile struct
+ */
+void
+restore_db(struct dbFILE *f)
+{
+ int errno_save = errno;
+
+ if (f->mode == 'w')
+ {
+ int ok = 0; /* Did we manage to restore the old file? */
+
+ errno = errno_save = 0;
+
+ if (f->backupname[0] && strcmp(f->backupname, f->filename))
+ if (rename(f->backupname, f->filename) == 0)
+ ok = 1;
+
+ if (!ok && f->backupfp)
+ {
+ char buf[1024];
+ size_t i;
+
+ ok = fseek(f->fp, 0, SEEK_SET) == 0;
+
+ while (ok && (i = fread(buf, 1, sizeof(buf), f->backupfp)) > 0)
+ if (fwrite(buf, 1, i, f->fp) != i)
+ ok = 0;
+
+ if (ok)
+ {
+ fflush(f->fp);
+ ftruncate(fileno(f->fp), ftell(f->fp));
+ }
+ }
+
+ if (!ok && errno > 0)
+ ilog(LOG_TYPE_IRCD, "Unable to restore backup of %s", f->filename);
+
+ errno_save = errno;
+
+ if (f->backupfp)
+ fclose(f->backupfp);
+ if (f->backupname[0])
+ unlink(f->backupname);
+ }
+
+ fclose(f->fp);
+
+ if (!errno_save)
+ errno_save = errno;
+
+ MyFree(f);
+ errno = errno_save;
+}
+
+/*! \brief Close a database file. If the file was opened for write, remove the
+ * backup we (may have) created earlier.
+ *
+ * \param dbFile struct
+ */
+void
+close_db(struct dbFILE *f)
+{
+ if (f->mode == 'w' && f->backupname[0] &&
+ strcmp(f->backupname, f->filename))
+ {
+ if (f->backupfp)
+ fclose(f->backupfp);
+
+ unlink(f->backupname);
+ }
+
+ fclose(f->fp);
+ MyFree(f);
+}
+
+/*
+ * Read and write 2-, 4- and 8-byte quantities, pointers, and strings. All
+ * multibyte values are stored in big-endian order (most significant byte
+ * first). A pointer is stored as a byte, either 0 if NULL or 1 if not,
+ * and read pointers are returned as either (void *)0 or (void *)1. A
+ * string is stored with a 2-byte unsigned length (including the trailing
+ * \0) first; a length of 0 indicates that the string pointer is NULL.
+ * Written strings are truncated silently at 65534 bytes, and are always
+ * null-terminated.
+ */
+
+/*! \brief Read a unsigned 8bit integer
+ *
+ * \param ret 8bit integer to read
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+read_uint8(unsigned char *ret, struct dbFILE *f)
+{
+ int c = fgetc(f->fp);
+
+ if (c == EOF)
+ return -1;
+
+ *ret = c;
+ return 0;
+}
+
+/*! \brief Write a 8bit integer
+ *
+ * \param ret 8bit integer to write
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+write_uint8(unsigned char val, struct dbFILE *f)
+{
+ if (fputc(val, f->fp) == EOF)
+ return -1;
+
+ return 0;
+}
+
+/*! \brief Read a unsigned 8bit integer
+ *
+ * \param ret 8bit integer to read
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+read_uint16(uint16_t *ret, struct dbFILE *f)
+{
+ int c1 = fgetc(f->fp);
+ int c2 = fgetc(f->fp);
+
+ if (c1 == EOF || c2 == EOF)
+ return -1;
+
+ *ret = c1 << 8 | c2;
+ return 0;
+}
+
+/*! \brief Write a unsigned 16bit integer
+ *
+ * \param ret 16bit integer to write
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+write_uint16(uint16_t val, struct dbFILE *f)
+{
+ if (fputc((val >> 8) & 0xFF, f->fp) == EOF ||
+ fputc(val & 0xFF, f->fp) == EOF)
+ return -1;
+
+ return 0;
+}
+
+/*! \brief Read a unsigned 32bit integer
+ *
+ * \param ret unsigned 32bit integer to read
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+read_uint32(uint32_t *ret, struct dbFILE *f)
+{
+ int c1 = fgetc(f->fp);
+ int c2 = fgetc(f->fp);
+ int c3 = fgetc(f->fp);
+ int c4 = fgetc(f->fp);
+
+ if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
+ return -1;
+
+ *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
+ return 0;
+}
+
+
+/*! \brief Write a unsigned 32bit integer
+ *
+ * \param ret unsigned 32bit integer to write
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+write_uint32(uint32_t val, struct dbFILE *f)
+{
+ if (fputc((val >> 24) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val >> 16) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val >> 8) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val) & 0xFF, f->fp) == EOF)
+ return -1;
+ return 0;
+}
+
+/*! \brief Read a unsigned 64bit integer
+ *
+ * \param ret unsigned 64bit integer to read
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+read_uint64(uint64_t *ret, struct dbFILE *f)
+{
+ int64_t c1 = fgetc(f->fp);
+ int64_t c2 = fgetc(f->fp);
+ int64_t c3 = fgetc(f->fp);
+ int64_t c4 = fgetc(f->fp);
+ int64_t c5 = fgetc(f->fp);
+ int64_t c6 = fgetc(f->fp);
+ int64_t c7 = fgetc(f->fp);
+ int64_t c8 = fgetc(f->fp);
+
+ if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF ||
+ c5 == EOF || c6 == EOF || c7 == EOF || c8 == EOF)
+ return -1;
+
+ *ret = c1 << 56 | c2 << 48 | c3 << 40 | c4 << 32 |
+ c5 << 24 | c6 << 16 | c7 << 8 | c8;
+ return 0;
+}
+
+
+/*! \brief Write a unsigned 64bit integer
+ *
+ * \param ret unsigned 64bit integer to write
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+write_uint64(uint64_t val, struct dbFILE *f)
+{
+ if (fputc((val >> 56) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val >> 48) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val >> 40) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val >> 32) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val >> 24) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val >> 16) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val >> 8) & 0xFF, f->fp) == EOF)
+ return -1;
+ if (fputc((val) & 0xFF, f->fp) == EOF)
+ return -1;
+ return 0;
+}
+
+/*! \brief Read Pointer
+ *
+ * \param ret pointer to read
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+read_ptr(void **ret, struct dbFILE *f)
+{
+ int c = fgetc(f->fp);
+
+ if (c == EOF)
+ return -1;
+
+ *ret = (c ? (void *)1 : (void *)0);
+ return 0;
+}
+
+
+/*! \brief Write Pointer
+ *
+ * \param ret pointer to write
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+write_ptr(const void *ptr, struct dbFILE *f)
+{
+ if (fputc(ptr ? 1 : 0, f->fp) == EOF)
+ return -1;
+ return 0;
+}
+
+/*! \brief Read String
+ *
+ * \param ret string
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+read_string(char **ret, struct dbFILE *f)
+{
+ char *s = NULL;
+ uint16_t len = 0;
+
+ if (read_uint16(&len, f) < 0)
+ return -1;
+
+ if (len == 0)
+ {
+ *ret = NULL;
+ return 0;
+ }
+
+ s = MyMalloc(len);
+
+ if (len != fread(s, 1, len, f->fp))
+ {
+ MyFree(s);
+ return -1;
+ }
+
+ *ret = s;
+ return 0;
+}
+
+/*! \brief Write String
+ *
+ * \param ret string
+ * \param dbFile struct
+ * \return -1 on error, 0 otherwise.
+ */
+int
+write_string(const char *s, struct dbFILE *f)
+{
+ uint32_t len = 0;
+
+ if (!s)
+ return write_uint16(0, f);
+
+ len = strlen(s);
+
+ if (len > 65534)
+ len = 65534;
+ if (write_uint16((uint16_t)(len + 1), f) < 0)
+ return -1;
+ if (len > 0 && fwrite(s, 1, len, f->fp) != len)
+ return -1;
+ if (fputc(0, f->fp) == EOF)
+ return -1;
+
+ return 0;
+}