aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-db3-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'e-util/e-db3-utils.c')
-rw-r--r--e-util/e-db3-utils.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/e-util/e-db3-utils.c b/e-util/e-db3-utils.c
new file mode 100644
index 0000000000..c1da265453
--- /dev/null
+++ b/e-util/e-db3-utils.c
@@ -0,0 +1,185 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include "config.h"
+
+#include "e-db3-utils.h"
+
+#include <db.h>
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-util.h>
+
+#if DB_VERSION_MAJOR != 3 || \
+ DB_VERSION_MINOR != 1 || \
+ DB_VERSION_PATCH != 17
+#error Including wrong DB3. Need libdb 3.1.17.
+#endif
+
+static char *
+get_check_filename (const char *filename)
+{
+ return g_strdup_printf ("%s-upgrading", filename);
+}
+
+static char *
+get_copy_filename (const char *filename)
+{
+ return g_strdup_printf ("%s-copy", filename);
+}
+
+static int
+cp_file (const char *src, const char *dest)
+{
+ int i;
+ int o;
+ char buffer[1024];
+ int length;
+ int place;
+
+ i = open (src, O_RDONLY);
+ if (i == -1)
+ return -1;
+ o = creat (dest, S_IREAD | S_IWRITE);
+ if (o == -1) {
+ close (i);
+ return -1;
+ }
+ while (1) {
+ length = read (i, &buffer, sizeof (buffer));
+
+ if (length == 0)
+ break;
+
+ if (length == -1) {
+ if (errno == EINTR)
+ continue;
+ else {
+ close (i);
+ close (o);
+ unlink (dest);
+ return -1;
+ }
+ }
+
+ place = 0;
+ while (length != 0) {
+ int count;
+ count = write (o, buffer + place, length);
+ if (count == -1) {
+ if (errno == EINTR)
+ continue;
+ else {
+ close (i);
+ close (o);
+ unlink (dest);
+ return -1;
+ }
+ }
+
+ length -= count;
+ place += count;
+ }
+ }
+ if (close (i))
+ return -1;
+ if (close (o))
+ return -1;
+ return 0;
+}
+
+static int
+touch_file (const char *file)
+{
+ int o;
+ o = creat (file, S_IREAD | S_IWRITE);
+ if (o == -1)
+ return -1;
+
+ if (close (o) == -1)
+ return -1;
+
+ return 0;
+}
+
+static int
+resume_upgrade (const char *filename, const char *copy_filename, const char *check_filename)
+{
+ DB *db;
+ int ret_val;
+
+ ret_val = db_create (&db, NULL, 0);
+
+ if (ret_val == 0)
+ ret_val = cp_file (copy_filename, filename);
+
+ if (ret_val == 0)
+ ret_val = db->upgrade (db, filename, 0);
+
+ if (ret_val == 0)
+ ret_val = unlink (check_filename);
+ if (ret_val == 0)
+ ret_val = unlink (copy_filename);
+
+ db->close (db, 0);
+
+ return ret_val;
+}
+
+int
+e_db3_utils_maybe_recover (const char *filename)
+{
+ int ret_val = 0;
+ char *copy_filename;
+ char *check_filename;
+
+ copy_filename = get_copy_filename (filename);
+ check_filename = get_check_filename (filename);
+
+ if (g_file_exists (check_filename)) {
+ ret_val = resume_upgrade(filename, copy_filename, check_filename);
+ } else if (g_file_exists (copy_filename)) {
+ unlink (copy_filename);
+ }
+
+ g_free (copy_filename);
+ g_free (check_filename);
+ return ret_val;
+}
+
+int
+e_db3_utils_upgrade_format (const char *filename)
+{
+ char *copy_filename;
+ char *check_filename;
+ DB *db;
+ int ret_val;
+
+ ret_val = db_create (&db, NULL, 0);
+ if (ret_val != 0)
+ return ret_val;
+
+ copy_filename = get_copy_filename (filename);
+ check_filename = get_check_filename (filename);
+
+ ret_val = cp_file (filename, copy_filename);
+
+ if (ret_val == 0)
+ ret_val = touch_file (check_filename);
+ if (ret_val == 0)
+ ret_val = db->upgrade (db, filename, 0);
+ if (ret_val == 0)
+ ret_val = unlink (check_filename);
+
+ if (ret_val == 0)
+ ret_val = unlink (copy_filename);
+
+ db->close (db, 0);
+
+ g_free (check_filename);
+ g_free (copy_filename);
+ return ret_val;
+}