[geocode-glib] ip-server: Add country and city DB updater
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geocode-glib] ip-server: Add country and city DB updater
- Date: Wed, 6 Mar 2013 10:38:11 +0000 (UTC)
commit 115b4382d849b7d26f55016e3308a73f2234451d
Author: Satabdi Das <satabdidas gmail com>
Date: Fri Mar 1 15:03:21 2013 +0530
ip-server: Add country and city DB updater
configure.ac | 4 +
geocode-glib/geocode-ip-server/Makefile.am | 3 +-
geocode-glib/geocode-ip-server/geoip-update.c | 220 +++++++++++++++++++++++++
3 files changed, 226 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 6fdfe54..48d5d3a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -68,6 +68,10 @@ PKG_CHECK_MODULES(GEOCODE_SERVER,
libsoup-2.4
geoip)
+# Requires for the database update
+PKG_CHECK_MODULES(GEOCODE_DBUPDATE,
+ gio-2.0 >= 2.34)
+
GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
AC_SUBST(GLIB_GENMARSHAL)
diff --git a/geocode-glib/geocode-ip-server/Makefile.am b/geocode-glib/geocode-ip-server/Makefile.am
index 74d58c9..76d774e 100644
--- a/geocode-glib/geocode-ip-server/Makefile.am
+++ b/geocode-glib/geocode-ip-server/Makefile.am
@@ -4,10 +4,11 @@ BUILT_GIRSOURCES =
AM_CFLAGS = -I$(top_srcdir) $(GEOCODE_SERVER_CFLAGS) $(COMMON_CFLAGS) $(WARN_CFLAGS) $(DISABLE_DEPRECATED)
-DGEOIP_DATABASE_PATH=\""$(GEOIP_DATABASE_PATH)"\"
-TEST_PROGS += geoip-lookup
+TEST_PROGS += geoip-lookup geoip-update
noinst_PROGRAMS = $(TEST_PROGS)
geoip_lookup_LDADD = $(GEOCODE_SERVER_LIBS)
+geoip_update_LDADD = $(GEOCODE_DBUPDATE_LIBS)
MAINTAINERCLEANFILES = Makefile.in
diff --git a/geocode-glib/geocode-ip-server/geoip-update.c b/geocode-glib/geocode-ip-server/geoip-update.c
new file mode 100644
index 0000000..ec80064
--- /dev/null
+++ b/geocode-glib/geocode-ip-server/geoip-update.c
@@ -0,0 +1,220 @@
+#include <stdio.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+static struct {
+ const char *uri;
+ const char *db_gz_name;
+ const char *db_name;
+} db_info_map[] = {
+ {"http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz",
+ "GeoLiteCity.dat.gz",
+ "GeoLiteCity.dat"
+ },
+ {"http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz",
+ "GeoIP.dat.gz",
+ "GeoIP.dat"
+ }
+};
+
+/* if_db_updated function returns TRUE on success and FALSE on failure.
+ * It sets the parameter - updated to TRUE or FALSE based on the status
+ * of last update of the database.
+ */
+static gboolean
+if_db_updated (GFile *db, GFile *db_local, gboolean *updated, GError **error)
+{
+ GFileInfo *db_info;
+ GFileInfo *db_local_info;
+ guint64 db_time;
+ guint64 db_local_time;
+
+ if (g_file_query_exists (db_local, NULL) == FALSE) {
+ *updated = FALSE;
+ return TRUE;
+ }
+
+ db_info = g_file_query_info (db,
+ "time::modified",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ error);
+ if (!db_info)
+ return FALSE;
+
+ db_local_info = g_file_query_info (db_local,
+ "time::modified",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ error);
+ if (!db_local_info) {
+ g_object_unref (db_info);
+ return FALSE;
+ }
+
+ db_time = g_file_info_get_attribute_uint64 (db_info, "time::modified");
+ db_local_time = g_file_info_get_attribute_uint64 (db_local_info, "time::modified");
+ if (db_time == db_local_time)
+ *updated = TRUE;
+ else
+ *updated = FALSE;
+
+ g_object_unref (db_info);
+ g_object_unref (db_local_info);
+
+ return TRUE;
+}
+
+static void
+decompress_db (GFile *db, const char *path)
+{
+ GFile *db_decomp;
+ GFile *db_decomp_tmp;
+ GError *error = NULL;
+ GZlibDecompressor *conv;
+ GInputStream *instream;
+ GInputStream *instream_conv;
+ GOutputStream *outstream;
+ char *tmp_db_path;
+
+ instream = (GInputStream *) g_file_read (db, NULL, &error);
+ if (!instream) {
+ g_print ("Error opening file: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ conv = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
+ instream_conv = (GInputStream *) g_converter_input_stream_new (instream, G_CONVERTER (conv));
+ g_object_unref (instream);
+
+ tmp_db_path = g_strdup_printf ("%s.%s", path, "tmp");
+ db_decomp_tmp = g_file_new_for_path (tmp_db_path);
+ g_free (tmp_db_path);
+ outstream = (GOutputStream *) g_file_replace (db_decomp_tmp,
+ NULL,
+ FALSE,
+ G_FILE_CREATE_NONE,
+ NULL,
+ &error);
+ if (!outstream) {
+ g_print ("Error creating file: %s\n", error->message);
+ g_error_free (error);
+ goto end;
+ }
+
+ if (g_output_stream_splice (outstream,
+ instream_conv,
+ 0,
+ NULL,
+ &error) == -1) {
+ g_print ("Error decompressing the database: %s\n", error->message);
+ g_object_unref (outstream);
+ g_error_free (error);
+ goto end;
+ }
+
+ if (g_output_stream_close (outstream,
+ NULL,
+ &error) == FALSE) {
+ g_print ("Error decompressing the database: %s\n", error->message);
+ g_error_free (error);
+ } else {
+ db_decomp = g_file_new_for_path (path);
+ if (g_file_move (db_decomp_tmp,
+ db_decomp,
+ G_FILE_COPY_OVERWRITE,
+ NULL,
+ NULL,
+ NULL,
+ &error) == FALSE) {
+ g_print ("Error moving the temporary database file to the" \
+ " original database file: %s\n", error->message);
+ g_error_free (error);
+ } else {
+ g_print ("Database updated\n");
+ }
+
+ g_object_unref (db_decomp);
+ }
+ g_object_unref (outstream);
+
+end:
+ g_object_unref (db_decomp_tmp);
+ g_object_unref (conv);
+ g_object_unref (instream_conv);
+}
+
+int
+main (int argc, char **argv)
+{
+
+ GError *error = NULL;
+ char *path = "/usr/share/GeoIP/";
+ guint i;
+ GOptionContext *context;
+ const GOptionEntry entries[] = {
+ { "dbpath", 0, 0, G_OPTION_ARG_STRING, &path, "The directory containing the databases", NULL
},
+ { NULL }
+ };
+
+ g_type_init ();
+
+ context = g_option_context_new ("- updates the city and country databases from Maxmind.");
+ g_option_context_add_main_entries (context, entries, NULL);
+ if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
+ g_print ("Option parsing failed: %s\n", error->message);
+ return 1;
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (db_info_map); i++) {
+ GFile *db_remote;
+ GFile *db_local;
+ char *db_path;
+ char *db_decompressed_path;
+ gboolean updated;
+
+ g_print ("Updating %s database\n", db_info_map[i].db_name);
+ db_remote = g_file_new_for_uri (db_info_map[i].uri);
+
+ db_path = g_build_filename (path, db_info_map[i].db_gz_name, NULL);
+ db_local = g_file_new_for_path (db_path);
+ g_free (db_path);
+
+ if (if_db_updated (db_remote, db_local, &updated, &error) == FALSE) {
+ g_print ("Could not update the database: %s\n", error->message);
+ g_error_free (error);
+ goto end_loop;
+ }
+ if (updated) {
+ g_print ("Database '%s' up to date\n", db_info_map[i].db_name);
+ goto end_loop;
+ }
+
+ /* Copying the dat.gz for future reference.
+ * Ever update checks the timestamp of the file
+ * to decide whether to download it or not.
+ */
+ if (g_file_copy (db_remote,
+ db_local,
+ G_FILE_COPY_OVERWRITE,
+ NULL,
+ NULL,
+ NULL,
+ &error) == FALSE) {
+ g_print ("Could not download the database: %s\n", error->message);
+ goto end_loop;
+ }
+
+ db_decompressed_path = g_build_filename (path, db_info_map[i].db_name, NULL);
+ decompress_db (db_local, db_decompressed_path);
+ g_free (db_decompressed_path);
+
+end_loop:
+ g_object_unref (db_remote);
+ g_object_unref (db_local);
+ error = NULL;
+ }
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]