From d09af1b80697c4ed02e420ca89f2675b14b0f47b Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Mon, 13 Jun 2011 13:33:30 +0200 Subject: move libreport into its own git ssh://git.fedorahosted.org/git/libreport.git --- libreport/src/lib/Makefile.am | 94 --- libreport/src/lib/abrt_dbus.c | 623 ------------------- libreport/src/lib/abrt_types.c | 37 -- libreport/src/lib/append_to_malloced_string.c | 27 - libreport/src/lib/binhex.c | 76 --- libreport/src/lib/concat_path_file.c | 37 -- libreport/src/lib/copy_file_recursive.c | 149 ----- libreport/src/lib/copyfd.c | 172 ------ libreport/src/lib/create_dump_dir.c | 85 --- libreport/src/lib/daemon_is_ok.c | 51 -- libreport/src/lib/dirsize.c | 110 ---- libreport/src/lib/dump_dir.c | 839 -------------------------- libreport/src/lib/encbase64.c | 93 --- libreport/src/lib/event_config.c | 366 ----------- libreport/src/lib/event_xml_parser.c | 469 -------------- libreport/src/lib/get_cmdline.c | 150 ----- libreport/src/lib/glib_support.c | 27 - libreport/src/lib/hash_sha1.c | 226 ------- libreport/src/lib/is_in_string_list.c | 30 - libreport/src/lib/iso_date_string.c | 31 - libreport/src/lib/kernel-tainted.c | 143 ----- libreport/src/lib/load_plugin_settings.c | 97 --- libreport/src/lib/logging.c | 148 ----- libreport/src/lib/make_descr.c | 262 -------- libreport/src/lib/overlapping_strcpy.c | 38 -- libreport/src/lib/parse_options.c | 251 -------- libreport/src/lib/parse_release.c | 81 --- libreport/src/lib/problem_data.c | 424 ------------- libreport/src/lib/read_write.c | 120 ---- libreport/src/lib/report.c | 129 ---- libreport/src/lib/report_event.conf | 47 -- libreport/src/lib/run_event.c | 551 ----------------- libreport/src/lib/skip_whitespace.c | 34 -- libreport/src/lib/spawn.c | 173 ------ libreport/src/lib/stdio_helpers.c | 84 --- libreport/src/lib/steal_directory.c | 58 -- libreport/src/lib/strbuf.c | 170 ------ libreport/src/lib/xatonum.c | 65 -- libreport/src/lib/xfuncs.c | 410 ------------- 39 files changed, 6977 deletions(-) delete mode 100644 libreport/src/lib/Makefile.am delete mode 100644 libreport/src/lib/abrt_dbus.c delete mode 100644 libreport/src/lib/abrt_types.c delete mode 100644 libreport/src/lib/append_to_malloced_string.c delete mode 100644 libreport/src/lib/binhex.c delete mode 100644 libreport/src/lib/concat_path_file.c delete mode 100644 libreport/src/lib/copy_file_recursive.c delete mode 100644 libreport/src/lib/copyfd.c delete mode 100644 libreport/src/lib/create_dump_dir.c delete mode 100644 libreport/src/lib/daemon_is_ok.c delete mode 100644 libreport/src/lib/dirsize.c delete mode 100644 libreport/src/lib/dump_dir.c delete mode 100644 libreport/src/lib/encbase64.c delete mode 100644 libreport/src/lib/event_config.c delete mode 100644 libreport/src/lib/event_xml_parser.c delete mode 100644 libreport/src/lib/get_cmdline.c delete mode 100644 libreport/src/lib/glib_support.c delete mode 100644 libreport/src/lib/hash_sha1.c delete mode 100644 libreport/src/lib/is_in_string_list.c delete mode 100644 libreport/src/lib/iso_date_string.c delete mode 100644 libreport/src/lib/kernel-tainted.c delete mode 100644 libreport/src/lib/load_plugin_settings.c delete mode 100644 libreport/src/lib/logging.c delete mode 100644 libreport/src/lib/make_descr.c delete mode 100644 libreport/src/lib/overlapping_strcpy.c delete mode 100644 libreport/src/lib/parse_options.c delete mode 100644 libreport/src/lib/parse_release.c delete mode 100644 libreport/src/lib/problem_data.c delete mode 100644 libreport/src/lib/read_write.c delete mode 100644 libreport/src/lib/report.c delete mode 100644 libreport/src/lib/report_event.conf delete mode 100644 libreport/src/lib/run_event.c delete mode 100644 libreport/src/lib/skip_whitespace.c delete mode 100644 libreport/src/lib/spawn.c delete mode 100644 libreport/src/lib/stdio_helpers.c delete mode 100644 libreport/src/lib/steal_directory.c delete mode 100644 libreport/src/lib/strbuf.c delete mode 100644 libreport/src/lib/xatonum.c delete mode 100644 libreport/src/lib/xfuncs.c (limited to 'libreport/src/lib') diff --git a/libreport/src/lib/Makefile.am b/libreport/src/lib/Makefile.am deleted file mode 100644 index f90f2f9f..00000000 --- a/libreport/src/lib/Makefile.am +++ /dev/null @@ -1,94 +0,0 @@ -# libreport - the stuff shared among most of abrt (like xmalloc, logging) -lib_LTLIBRARIES = \ - libreport.la \ - libabrt_dbus.la - -# Not used just yet: -# time.cpp -# xconnect.cpp - -libreport_la_SOURCES = \ - xfuncs.c \ - is_in_string_list.c \ - encbase64.c \ - binhex.c \ - stdio_helpers.c \ - hash_sha1.c \ - read_write.c \ - logging.c \ - copyfd.c \ - copy_file_recursive.c \ - concat_path_file.c \ - append_to_malloced_string.c \ - overlapping_strcpy.c \ - skip_whitespace.c \ - glib_support.c \ - iso_date_string.c \ - strbuf.c \ - xatonum.c \ - spawn.c \ - dirsize.c \ - dump_dir.c \ - get_cmdline.c \ - load_plugin_settings.c \ - make_descr.c \ - run_event.c \ - problem_data.c \ - create_dump_dir.c \ - abrt_types.c \ - parse_release.c \ - parse_options.c \ - steal_directory.c \ - event_xml_parser.c \ - event_config.c \ - kernel-tainted.c \ - report.c -libreport_la_CPPFLAGS = \ - -Wall -Wwrite-strings -Werror \ - -I$(srcdir)/../include \ - -DLOCALSTATEDIR='"$(localstatedir)"' \ - -DVAR_RUN=\"$(VAR_RUN)\" \ - -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ - -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ - -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ - -DCONF_DIR=\"$(CONF_DIR)\" \ - -DEVENTS_DIR=\"$(EVENTS_DIR)\" \ - -DBIN_DIR=\"$(bindir)\" \ - $(GLIB_CFLAGS) \ - -D_GNU_SOURCE -libreport_la_LDFLAGS = \ - -version-info 0:1:0 -libreport_la_LIBADD = \ - $(GLIB_LIBS) - -libreportconfdir = $(CONF_DIR) -dist_libreportconf_DATA = \ - report_event.conf - -libabrt_dbus_la_SOURCES = \ - abrt_dbus.c -libabrt_dbus_la_CPPFLAGS = \ - -I$(srcdir)/../include/report -I$(srcdir)/../include \ - -DLOCALSTATEDIR='"$(localstatedir)"' \ - -DVAR_RUN=\"$(VAR_RUN)\" \ - -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ - -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ - -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ - -DCONF_DIR=\"$(CONF_DIR)\" \ - -DEVENTS_DIR=\"$(EVENTS_DIR)\" \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) \ - -Wall -Wwrite-strings -Werror \ - -D_GNU_SOURCE -libabrt_dbus_la_LDFLAGS = \ - -version-info 0:1:0 -libabrt_dbus_la_LIBADD = \ - libreport.la \ - $(GLIB_LIBS) \ - $(DBUS_LIBS) - -$(DESTDIR)/$(DEBUG_DUMPS_DIR): - $(mkdir_p) '$@' -# no need to chmod it here -#chmod 1777 '$@' -install-data-local: $(DESTDIR)/$(DEBUG_DUMPS_DIR) diff --git a/libreport/src/lib/abrt_dbus.c b/libreport/src/lib/abrt_dbus.c deleted file mode 100644 index d412ad5c..00000000 --- a/libreport/src/lib/abrt_dbus.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include -//#include "abrtlib.h" -#include "abrt_dbus.h" - -DBusConnection* g_dbus_conn; - - -/* - * Helpers for building DBus messages - */ - -//void store_bool(DBusMessageIter* iter, bool val) -//{ -// dbus_bool_t db = val; -// if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &db)) -// die_out_of_memory(); -//} -void store_int32(DBusMessageIter* iter, int32_t val) -{ - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &val)) - die_out_of_memory(); -} -void store_uint32(DBusMessageIter* iter, uint32_t val) -{ - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &val)) - die_out_of_memory(); -} -void store_int64(DBusMessageIter* iter, int64_t val) -{ - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_INT64, &val)) - die_out_of_memory(); -} -void store_uint64(DBusMessageIter* iter, uint64_t val) -{ - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &val)) - die_out_of_memory(); -} - -/* dbus daemon will simply close our connection if we send broken utf8. - * Therefore we must never do that. - */ -static char *sanitize_utf8(const char *src) -{ - const char *initial_src = src; - char *sanitized = NULL; - unsigned sanitized_pos = 0; - - while (*src) - { - int bytes = 0; - - unsigned c = (unsigned char) *src; - if (c <= 0x7f) - { - bytes = 1; - goto good_byte; - } - - /* Unicode -> utf8: */ - /* 80-7FF -> 110yyyxx 10xxxxxx */ - /* 800-FFFF -> 1110yyyy 10yyyyxx 10xxxxxx */ - /* 10000-1FFFFF -> 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx */ - /* 200000-3FFFFFF -> 111110tt 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx */ - /* 4000000-FFFFFFFF -> 111111tt 10tttttt 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx */ - do { - c <<= 1; - bytes++; - } while ((c & 0x80) && bytes < 6); - if (bytes == 1) - { - /* A bare "continuation" byte. Say, 80 */ - goto bad_byte; - } - - c = (uint8_t)(c) >> bytes; - { - const char *pp = src; - int cnt = bytes; - while (--cnt) - { - unsigned ch = (unsigned char) *++pp; - if ((ch & 0xc0) != 0x80) /* Missing "continuation" byte. Example: e0 80 */ - { - goto bad_byte; - } - c = (c << 6) + (ch & 0x3f); - } - } - /* TODO */ - /* Need to check that c isn't produced by overlong encoding */ - /* Example: 11000000 10000000 converts to NUL */ - /* 11110000 10000000 10000100 10000000 converts to 0x100 */ - /* correct encoding: 11000100 10000000 */ - if (c <= 0x7f) /* crude check: only catches bad encodings which map to chars <= 7f */ - { - goto bad_byte; - } - - good_byte: - while (--bytes >= 0) - { - c = (unsigned char) *src++; - if (sanitized) - { - sanitized = (char*) xrealloc(sanitized, sanitized_pos + 2); - sanitized[sanitized_pos++] = c; - sanitized[sanitized_pos] = '\0'; - } - } - continue; - - bad_byte: - if (!sanitized) - { - sanitized_pos = src - initial_src; - sanitized = xstrndup(initial_src, sanitized_pos); - } - sanitized = (char*) xrealloc(sanitized, sanitized_pos + 5); - sanitized[sanitized_pos++] = '['; - c = (unsigned char) *src++; - sanitized[sanitized_pos++] = "0123456789ABCDEF"[c >> 4]; - sanitized[sanitized_pos++] = "0123456789ABCDEF"[c & 0xf]; - sanitized[sanitized_pos++] = ']'; - sanitized[sanitized_pos] = '\0'; - } - - if (sanitized) - VERB2 log("note: bad utf8, converted '%s' -> '%s'", initial_src, sanitized); - - return sanitized; /* usually NULL: the whole string is ok */ -} -void store_string(DBusMessageIter* iter, const char* val) -{ - const char *sanitized = sanitize_utf8(val); - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, sanitized ? &sanitized : &val)) - die_out_of_memory(); - free((char*)sanitized); -} - - -/* - * Helpers for parsing DBus messages - */ - -//int load_bool(DBusMessageIter* iter, bool& val) -//{ -// int type = dbus_message_iter_get_arg_type(iter); -// if (type != DBUS_TYPE_BOOLEAN) -// error_msg_and_die("%s expected in dbus message, but not found ('%c')", "bool", type); -// dbus_bool_t db; -// dbus_message_iter_get_basic(iter, &db); -// val = db; -// return dbus_message_iter_next(iter); -//} -int load_int32(DBusMessageIter* iter, int32_t *val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_INT32) - { - error_msg("%s expected in dbus message, but not found ('%c')", "int32", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); - return dbus_message_iter_next(iter); -} -int load_uint32(DBusMessageIter* iter, uint32_t *val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_UINT32) - { - error_msg("%s expected in dbus message, but not found ('%c')", "uint32", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); - return dbus_message_iter_next(iter); -} -int load_int64(DBusMessageIter* iter, int64_t *val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_INT64) - { - error_msg("%s expected in dbus message, but not found ('%c')", "int64", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); - return dbus_message_iter_next(iter); -} -int load_uint64(DBusMessageIter* iter, uint64_t *val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_UINT64) - { - error_msg("%s expected in dbus message, but not found ('%c')", "uint64", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); - return dbus_message_iter_next(iter); -} -int load_charp(DBusMessageIter* iter, const char** val) -{ - *val = NULL; - - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_STRING) - { - error_msg("%s expected in dbus message, but not found ('%c')", "string", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); -//log("load_charp:'%s'", *val); - return dbus_message_iter_next(iter); -} - - -/* - * Glib integration machinery - */ - -/* Callback: "glib says dbus fd is active" */ -static gboolean handle_dbus_fd(GIOChannel *gio, GIOCondition condition, gpointer data) -{ - DBusWatch *watch = (DBusWatch*)data; - - VERB3 log("%s(gio, condition:%x [bits:IN/PRI/OUT/ERR/HUP...], data)", __func__, (int)condition); - - /* Notify the D-Bus library when a previously-added watch - * is ready for reading or writing, or has an exception such as a hangup. - */ - int glib_flags = (int)condition; - int dbus_flags = 0; - if (glib_flags & G_IO_IN) dbus_flags |= DBUS_WATCH_READABLE; - if (glib_flags & G_IO_OUT) dbus_flags |= DBUS_WATCH_WRITABLE; - if (glib_flags & G_IO_ERR) dbus_flags |= DBUS_WATCH_ERROR; - if (glib_flags & G_IO_HUP) dbus_flags |= DBUS_WATCH_HANGUP; - /* - * TODO: - * If dbus_watch_handle returns FALSE, then the file descriptor - * may still be ready for reading or writing, but more memory - * is needed in order to do the reading or writing. If you ignore - * the FALSE return, your application may spin in a busy loop - * on the file descriptor until memory becomes available, - * but nothing more catastrophic should happen. - */ - dbus_watch_handle(watch, dbus_flags); - - while (dbus_connection_dispatch(g_dbus_conn) == DBUS_DISPATCH_DATA_REMAINS) - VERB3 log("%s: more data to process, looping", __func__); - return TRUE; /* "glib, do not remove this event source!" */ -} - -typedef struct watch_app_info_t -{ - GIOChannel *channel; - guint event_source_id; - bool watch_enabled; -} watch_app_info_t; -/* Callback: "dbus_watch_get_enabled() may return a different value than it did before" */ -static void toggled_watch(DBusWatch *watch, void* data) -{ - VERB3 log("%s(watch:%p, data)", __func__, watch); - - watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); - if (dbus_watch_get_enabled(watch)) - { - if (!app_info->watch_enabled) - { - app_info->watch_enabled = true; - int dbus_flags = dbus_watch_get_flags(watch); - int glib_flags = 0; - if (dbus_flags & DBUS_WATCH_READABLE) glib_flags |= G_IO_IN; - if (dbus_flags & DBUS_WATCH_WRITABLE) glib_flags |= G_IO_OUT; - VERB3 log(" adding watch to glib main loop. dbus_flags:%x glib_flags:%x", dbus_flags, glib_flags); - app_info->event_source_id = g_io_add_watch(app_info->channel, (GIOCondition)glib_flags, handle_dbus_fd, watch); - } - /* else: it was already enabled */ - } - else - { - if (app_info->watch_enabled) - { - app_info->watch_enabled = false; - /* does it free the hidden GSource too? */ - VERB3 log(" removing watch from glib main loop"); - g_source_remove(app_info->event_source_id); - } - /* else: it was already disabled */ - } -} -/* Callback: "libdbus needs a new watch to be monitored by the main loop" */ -static dbus_bool_t add_watch(DBusWatch *watch, void* data) -{ - VERB3 log("%s(watch:%p, data)", __func__, watch); - - watch_app_info_t* app_info = (watch_app_info_t*)xzalloc(sizeof(*app_info)); - dbus_watch_set_data(watch, app_info, free); - - int fd = dbus_watch_get_unix_fd(watch); - VERB3 log(" dbus_watch_get_unix_fd():%d", fd); - app_info->channel = g_io_channel_unix_new(fd); - /* _unconditionally_ adding it to event loop would be an error */ - toggled_watch(watch, data); - return TRUE; -} -/* Callback: "libdbus no longer needs a watch to be monitored by the main loop" */ -static void remove_watch(DBusWatch *watch, void* data) -{ - VERB3 log("%s()", __func__); - watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); - if (app_info->watch_enabled) - { - app_info->watch_enabled = false; - g_source_remove(app_info->event_source_id); - } - g_io_channel_unref(app_info->channel); -} - -/* Callback: "libdbus needs a new timeout to be monitored by the main loop" */ -static dbus_bool_t add_timeout(DBusTimeout *timeout, void* data) -{ - VERB3 log("%s()", __func__); - return TRUE; -} -/* Callback: "libdbus no longer needs a timeout to be monitored by the main loop" */ -static void remove_timeout(DBusTimeout *timeout, void* data) -{ - VERB3 log("%s()", __func__); -} -/* Callback: "dbus_timeout_get_enabled() may return a different value than it did before" */ -static void timeout_toggled(DBusTimeout *timeout, void* data) -{ -//seems to be never called, let's make it noisy - error_msg_and_die("%s(): FIXME: some dbus machinery is missing here", __func__); -} - -/* Callback: "DBusObjectPathVTable is unregistered (or its connection is freed)" */ -static void unregister_vtable(DBusConnection *conn, void* data) -{ - VERB3 log("%s()", __func__); -} - - -/* - * Simple logging handler for dbus errors. - */ -int log_dbus_error(const char *msg, DBusError *err) -{ - int ret = 0; - if (dbus_error_is_set(err)) - { - error_msg("dbus error: %s", err->message); - ret = 1; - } - if (msg) - { - error_msg(msg); - ret = 1; - } - return ret; -} - - -/* - * Initialization. Works as follows: - * - * we have a DBusConnection* (say, obtained with dbus_bus_get) - * we call dbus_connection_set_watch_functions - * libdbus calls back add_watch(watch:0x2341090, data), this watch is for writing - * we call toggled_watch, but it finds that watch is not to be enabled yet - * libdbus calls back add_watch(watch:0x23410e0, data), this watch is for reading - * we call toggled_watch, it adds watch's fd to glib main loop with POLLIN - * (note: these watches are different objects, but they have the same fd) - * we call dbus_connection_set_timeout_functions - * we call dbus_connection_register_object_path - * - * Note: if user will later call dbus_bus_request_name(conn, ...): - * libdbus calls back add_timeout() - * libdbus calls back remove_timeout() - * note - no callback to timeout_toggled()! - * (therefore there is no code yet in timeout_toggled (see above), it's not used) - */ -void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn, - const char* object_path, - DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data) -) { - if (g_dbus_conn) - error_msg_and_die("Internal bug: can't connect to more than one dbus"); - g_dbus_conn = conn; - -//do we need this? why? -//log("dbus_connection_set_dispatch_status_function"); -// dbus_connection_set_dispatch_status_function(conn, -// dispatch, /* void dispatch(DBusConnection *conn, DBusDispatchStatus new_status, void* data) */ -// NULL, /* data */ -// NULL /* free_data_function */ -// ) - VERB3 log("dbus_connection_set_watch_functions"); - if (!dbus_connection_set_watch_functions(conn, - add_watch, - remove_watch, - toggled_watch, - NULL, /* data */ - NULL /* free_data_function */ - ) - ) { - die_out_of_memory(); - } - VERB3 log("dbus_connection_set_timeout_functions"); - if (!dbus_connection_set_timeout_functions(conn, - add_timeout, - remove_timeout, - timeout_toggled, - NULL, /* data */ - NULL /* free_data_function */ - ) - ) { - die_out_of_memory(); - } - - if (object_path && message_received_func) - { - /* Table */ - const DBusObjectPathVTable vtable = { - /* .unregister_function = */ unregister_vtable, - /* .message_function = */ message_received_func, - }; - VERB3 log("dbus_connection_register_object_path"); - if (!dbus_connection_register_object_path(conn, - object_path, - &vtable, - NULL /* data */ - ) - ) { - die_out_of_memory(); - } - } -} - - -/* - * Support functions for clients - */ - -/* helpers */ -static DBusMessage* new_call_msg(const char* method) -{ - DBusMessage* msg = dbus_message_new_method_call(ABRTD_DBUS_NAME, ABRTD_DBUS_PATH, ABRTD_DBUS_IFACE, method); - if (!msg) - die_out_of_memory(); - return msg; -} - -static DBusMessage* send_get_reply_and_unref(DBusMessage* msg) -{ - dbus_uint32_t serial; - if (TRUE != dbus_connection_send(g_dbus_conn, msg, &serial)) - error_msg_and_die("Error sending DBus message"); - dbus_message_unref(msg); - - while (true) - { - DBusMessage *received = dbus_connection_pop_message(g_dbus_conn); - if (!received) - { - if (FALSE == dbus_connection_read_write(g_dbus_conn, -1)) - error_msg_and_die("dbus connection closed"); - continue; - } - - int tp = dbus_message_get_type(received); - const char *error_str = dbus_message_get_error_name(received); -#if 0 - /* Debugging */ - printf("type:%u (CALL:%u, RETURN:%u, ERROR:%u, SIGNAL:%u)\n", tp, - DBUS_MESSAGE_TYPE_METHOD_CALL, - DBUS_MESSAGE_TYPE_METHOD_RETURN, - DBUS_MESSAGE_TYPE_ERROR, - DBUS_MESSAGE_TYPE_SIGNAL - ); - const char *sender = dbus_message_get_sender(received); - if (sender) - printf("sender: %s\n", sender); - const char *path = dbus_message_get_path(received); - if (path) - printf("path: %s\n", path); - const char *member = dbus_message_get_member(received); - if (member) - printf("member: %s\n", member); - const char *interface = dbus_message_get_interface(received); - if (interface) - printf("interface: %s\n", interface); - const char *destination = dbus_message_get_destination(received); - if (destination) - printf("destination: %s\n", destination); - if (error_str) - printf("error: '%s'\n", error_str); -#endif - - DBusError err; - dbus_error_init(&err); - - if (dbus_message_is_signal(received, ABRTD_DBUS_IFACE, "Update")) - { - const char *update_msg; - if (!dbus_message_get_args(received, &err, - DBUS_TYPE_STRING, &update_msg, - DBUS_TYPE_INVALID)) - { - error_msg_and_die("dbus Update message: arguments mismatch"); - } - printf(">> %s\n", update_msg); - } - else if (dbus_message_is_signal(received, ABRTD_DBUS_IFACE, "Warning")) - { - const char *warning_msg; - if (!dbus_message_get_args(received, &err, - DBUS_TYPE_STRING, &warning_msg, - DBUS_TYPE_INVALID)) - { - error_msg_and_die("dbus Warning message: arguments mismatch"); - } - log(">! %s", warning_msg); - } - else - if (tp == DBUS_MESSAGE_TYPE_METHOD_RETURN - && dbus_message_get_reply_serial(received) == serial - ) { - return received; - } - else - if (tp == DBUS_MESSAGE_TYPE_ERROR - && dbus_message_get_reply_serial(received) == serial - ) { - error_msg_and_die("dbus call returned error: '%s'", error_str); - } - - dbus_message_unref(received); - } -} - -int32_t call_DeleteDebugDump(const char *dump_dir_name) -{ - DBusMessage* msg = new_call_msg(__func__ + 5); - dbus_message_append_args(msg, - DBUS_TYPE_STRING, &dump_dir_name, - DBUS_TYPE_INVALID); - - DBusMessage *reply = send_get_reply_and_unref(msg); - - DBusMessageIter in_iter; - dbus_message_iter_init(reply, &in_iter); - - int32_t result; - int r = load_int32(&in_iter, &result); - if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ - error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); - - dbus_message_unref(reply); - return result; -} - -static int connect_to_abrtd_and_call_DeleteDebugDump(const char *dump_dir_name) -{ - DBusError err; - dbus_error_init(&err); - g_dbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - if (log_dbus_error( - g_dbus_conn ? NULL : - "error requesting system DBus, possible reasons: " - "dbus config is incorrect; dbus-daemon is not running, " - "or dbus daemon needs to be restarted to reload dbus config", - &err - ) - ) { - if (g_dbus_conn) - dbus_connection_unref(g_dbus_conn); - g_dbus_conn = NULL; - return 1; - } - - int ret = call_DeleteDebugDump(dump_dir_name); - if (ret == ENOENT) - error_msg("Dump directory '%s' is not found", dump_dir_name); - else if (ret != 0) - error_msg("Can't delete dump directory '%s'", dump_dir_name); - - dbus_connection_unref(g_dbus_conn); - g_dbus_conn = NULL; - - return ret; -} - -int delete_dump_dir_possibly_using_abrtd(const char *dump_dir_name) -{ - /* Try to delete it ourselves */ - struct dump_dir *dd = dd_opendir(dump_dir_name, DD_OPEN_READONLY); - if (dd) - { - if (dd->locked) /* it is not readonly */ - return dd_delete(dd); - dd_close(dd); - } - - VERB1 log("Deleting '%s' via abrtd dbus call", dump_dir_name); - return connect_to_abrtd_and_call_DeleteDebugDump(dump_dir_name); -} diff --git a/libreport/src/lib/abrt_types.c b/libreport/src/lib/abrt_types.c deleted file mode 100644 index 0b51821d..00000000 --- a/libreport/src/lib/abrt_types.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - Copyright (C) 2010 ABRT Team - Copyright (C) 2010 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "libreport.h" - -map_string_h *new_map_string(void) -{ - return g_hash_table_new_full(g_str_hash, g_str_equal, free, free); -} - -void free_map_string(map_string_h *ms) -{ - if (ms) - g_hash_table_destroy(ms); -} - -const char *get_map_string_item_or_empty(map_string_h *ms, const char *key) -{ - const char *v = (const char*)g_hash_table_lookup(ms, key); - if (!v) v = ""; - return v; -} diff --git a/libreport/src/lib/append_to_malloced_string.c b/libreport/src/lib/append_to_malloced_string.c deleted file mode 100644 index c55a258f..00000000 --- a/libreport/src/lib/append_to_malloced_string.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "libreport.h" - -char *append_to_malloced_string(char *mstr, const char *append) -{ - unsigned mlen = strlen(mstr); - mstr = (char*) xrealloc(mstr, mlen + strlen(append) + 1); - strcpy(mstr + mlen, append); - return mstr; -} diff --git a/libreport/src/lib/binhex.c b/libreport/src/lib/binhex.c deleted file mode 100644 index ed6dea08..00000000 --- a/libreport/src/lib/binhex.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (C) 2011 ABRT team - Copyright (C) 2011 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "libreport.h" - -static const char hexdigits_locase[] = "0123456789abcdef"; - -/* Emit a string of hex representation of bytes */ -char *bin2hex(char *dst, const char *str, int count) -{ - while (count) { - unsigned char c = *str++; - /* put lowercase hex digits */ - *dst++ = hexdigits_locase[c >> 4]; - *dst++ = hexdigits_locase[c & 0xf]; - count--; - } - return dst; -} - -/* Convert "xxxxxxxx" hex string to binary, no more than COUNT bytes */ -char *hex2bin(char *dst, const char *str, int count) -{ - /* Parts commented out with // allow parsing - * of strings like "xx:x:x:xx:xx:xx:xxxxxx" - * (IPv6, ethernet addresses and the like). - */ - errno = EINVAL; - while (*str && count) { - uint8_t val; - uint8_t c; - - c = *str++; - if (isdigit(c)) - val = c - '0'; - else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') - val = (c|0x20) - ('a' - 10); - else - return NULL; - val <<= 4; - c = *str; - if (isdigit(c)) - val |= c - '0'; - else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') - val |= (c|0x20) - ('a' - 10); - //else if (c == ':' || c == '\0') - // val >>= 4; - else - return NULL; - - *dst++ = val; - //if (c != '\0') - str++; - //if (*str == ':') - // str++; - count--; - } - errno = (*str ? ERANGE : 0); - return dst; -} diff --git a/libreport/src/lib/concat_path_file.c b/libreport/src/lib/concat_path_file.c deleted file mode 100644 index d7f199a5..00000000 --- a/libreport/src/lib/concat_path_file.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Utility routines. - * - * Copyright (C) 2001 Erik Andersen - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* Concatenate path and filename to new allocated buffer. - * Add '/' only as needed (no duplicate // are produced). - * If path is NULL, it is assumed to be "/". - * filename should not be NULL. - */ - -#include "libreport.h" - -char *concat_path_file(const char *path, const char *filename) -{ - if (!path) - path = ""; - const char *end = path + strlen(path); - while (*filename == '/') - filename++; - return xasprintf("%s%s%s", path, (end != path && end[-1] != '/' ? "/" : ""), filename); -} diff --git a/libreport/src/lib/copy_file_recursive.c b/libreport/src/lib/copy_file_recursive.c deleted file mode 100644 index ebfd8dae..00000000 --- a/libreport/src/lib/copy_file_recursive.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (C) 2011 ABRT team - Copyright (C) 2011 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "libreport.h" - -int copy_file_recursive(const char *source, const char *dest) -{ - /* This is a recursive function, try to minimize stack usage */ - /* NB: each struct stat is ~100 bytes */ - struct stat source_stat; - struct stat dest_stat; - int retval = 0; - int dest_exists = 0; - - if (strcmp(source, ".lock") == 0) - goto skip; - - if (stat(source, &source_stat) < 0) { - perror_msg("Can't stat '%s'", source); - return -1; - } - - if (lstat(dest, &dest_stat) < 0) { - if (errno != ENOENT) { - perror_msg("Can't stat '%s'", dest); - return -1; - } - } else { - if (source_stat.st_dev == dest_stat.st_dev - && source_stat.st_ino == dest_stat.st_ino - ) { - error_msg("'%s' and '%s' are the same file", source, dest); - return -1; - } - dest_exists = 1; - } - - if (S_ISDIR(source_stat.st_mode)) { - DIR *dp; - struct dirent *d; - - if (dest_exists) { - if (!S_ISDIR(dest_stat.st_mode)) { - error_msg("Target '%s' is not a directory", dest); - return -1; - } - /* race here: user can substitute a symlink between - * this check and actual creation of files inside dest */ - } else { - /* Create DEST */ - mode_t mode = source_stat.st_mode; - /* Allow owner to access new dir (at least for now) */ - mode |= S_IRWXU; - if (mkdir(dest, mode) < 0) { - perror_msg("Can't create directory '%s'", dest); - return -1; - } - } - /* Recursively copy files in SOURCE */ - dp = opendir(source); - if (dp == NULL) { - retval = -1; - goto ret; - } - - while (retval == 0 && (d = readdir(dp)) != NULL) { - char *new_source, *new_dest; - - if (dot_or_dotdot(d->d_name)) - continue; - new_source = concat_path_file(source, d->d_name); - new_dest = concat_path_file(dest, d->d_name); - if (copy_file_recursive(new_source, new_dest) < 0) - retval = -1; - free(new_source); - free(new_dest); - } - closedir(dp); - - goto ret; - } - - if (S_ISREG(source_stat.st_mode)) { - int src_fd; - int dst_fd; - mode_t new_mode; - - src_fd = open(source, O_RDONLY); - if (src_fd < 0) { - perror_msg("Can't open '%s'", source); - return -1; - } - - /* Do not try to open with weird mode fields */ - new_mode = source_stat.st_mode; - - // security problem versus (sym)link attacks - // dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode); - /* safe way: */ - dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode); - if (dst_fd < 0) { - close(src_fd); - return -1; - } - - if (copyfd_eof(src_fd, dst_fd, COPYFD_SPARSE) == -1) - retval = -1; - close(src_fd); - /* Careful: do check that buffered writes succeeded... */ - if (close(dst_fd) < 0) { - perror_msg("Error writing to '%s'", dest); - retval = -1; - } else { - /* (Try to) copy atime and mtime */ - struct timeval atime_mtime[2]; - atime_mtime[0].tv_sec = source_stat.st_atime; - // note: if "st_atim.tv_nsec" doesn't compile, try "st_atimensec": - atime_mtime[0].tv_usec = source_stat.st_atim.tv_nsec / 1000; - atime_mtime[1].tv_sec = source_stat.st_mtime; - atime_mtime[1].tv_usec = source_stat.st_mtim.tv_nsec / 1000; - // note: can use utimensat when it is more widely supported: - utimes(dest, atime_mtime); - } - goto ret; - } - - /* Neither dir not regular file: skip */ - - skip: - log("Skipping '%s'", source); - ret: - return retval; -} diff --git a/libreport/src/lib/copyfd.c b/libreport/src/lib/copyfd.c deleted file mode 100644 index 8d805069..00000000 --- a/libreport/src/lib/copyfd.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -/* - * Utility routines. - * - */ -#include "libreport.h" - -#define CONFIG_FEATURE_COPYBUF_KB 4 - -static const char msg_write_error[] = "write error"; -static const char msg_read_error[] = "read error"; - -static off_t full_fd_action(int src_fd, int dst_fd, off_t size, int flags) -{ - int status = -1; - off_t total = 0; - int last_was_seek = 0; -#if CONFIG_FEATURE_COPYBUF_KB <= 4 - char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; - enum { buffer_size = sizeof(buffer) }; -#else - char *buffer; - int buffer_size; - - /* We want page-aligned buffer, just in case kernel is clever - * and can do page-aligned io more efficiently */ - buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, - /* ignored: */ -1, 0); - buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; - if (buffer == MAP_FAILED) { - buffer = alloca(4 * 1024); - buffer_size = 4 * 1024; - } -#endif - - if (src_fd < 0) - goto out; - - if (!size) { - size = buffer_size; - status = 1; /* copy until eof */ - } - - while (1) { - ssize_t rd; - - rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size); - - if (!rd) { /* eof - all done */ - if (last_was_seek) { - if (lseek(dst_fd, -1, SEEK_CUR) < 0 - || safe_write(dst_fd, "", 1) != 1 - ) { - perror_msg("%s", msg_write_error); - break; - } - } - status = 0; - break; - } - if (rd < 0) { - perror_msg("%s", msg_read_error); - break; - } - /* dst_fd == -1 is a fake, else... */ - if (dst_fd >= 0) { - if (flags & COPYFD_SPARSE) { - ssize_t cnt = rd; - while (--cnt >= 0) - if (buffer[cnt] != 0) - goto need2write; - if (lseek(dst_fd, rd, SEEK_CUR) < 0) { - flags &= ~COPYFD_SPARSE; - goto need2write; - } - last_was_seek = 1; - } else { - need2write: - { - ssize_t wr = full_write(dst_fd, buffer, rd); - if (wr < rd) { - perror_msg("%s", msg_write_error); - break; - } - last_was_seek = 0; - } - } - } - total += rd; - if (status < 0) { /* if we aren't copying till EOF... */ - size -= rd; - if (!size) { - /* 'size' bytes copied - all done */ - status = 0; - break; - } - } - } - out: - -#if CONFIG_FEATURE_COPYBUF_KB > 4 - if (buffer_size != 4 * 1024) - munmap(buffer, buffer_size); -#endif - return status ? -1 : total; -} - -off_t copyfd_size(int fd1, int fd2, off_t size, int flags) -{ - if (size) { - return full_fd_action(fd1, fd2, size, flags); - } - return 0; -} - -void copyfd_exact_size(int fd1, int fd2, off_t size) -{ - off_t sz = copyfd_size(fd1, fd2, size, /*flags:*/ 0); - if (sz == size) - return; - if (sz != -1) - error_msg_and_die("short read"); - /* if sz == -1, copyfd_XX already complained */ - xfunc_die(); -} - -off_t copyfd_eof(int fd1, int fd2, int flags) -{ - return full_fd_action(fd1, fd2, 0, flags); -} - -off_t copy_file(const char *src_name, const char *dst_name, int mode) -{ - off_t r; - int src = open(src_name, O_RDONLY); - if (src < 0) - { - perror_msg("Can't open '%s'", src_name); - return -1; - } - int dst = open(dst_name, O_WRONLY | O_TRUNC | O_CREAT, mode); - if (dst < 0) - { - close(src); - perror_msg("Can't open '%s'", dst_name); - return -1; - } - r = copyfd_eof(src, dst, /*flags:*/ 0); - close(src); - close(dst); - return r; -} diff --git a/libreport/src/lib/create_dump_dir.c b/libreport/src/lib/create_dump_dir.c deleted file mode 100644 index 33d9bd7c..00000000 --- a/libreport/src/lib/create_dump_dir.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "libreport.h" - -static struct dump_dir *try_dd_create(const char *base_dir_name, const char *dir_name) -{ - char *path = concat_path_file(base_dir_name, dir_name); - struct dump_dir *dd = dd_create(path, (uid_t)-1L, 0640); - if (dd) - dd_create_basic_files(dd, (uid_t)-1L); - free(path); - return dd; -} - -struct dump_dir *create_dump_dir_from_problem_data(problem_data_t *problem_data, const char *base_dir_name) -{ - char dir_name[sizeof("abrt-tmp-YYYY-MM-DD-HH:MM:SS-%lu") + sizeof(long)*3]; - sprintf(dir_name, "abrt-tmp-%s-%lu", iso_date_string(NULL), (long)getpid()); - - struct dump_dir *dd; - if (base_dir_name) - dd = try_dd_create(base_dir_name, dir_name); - else - { - /* Try /var/run/abrt */ - dd = try_dd_create(LOCALSTATEDIR"/run/abrt", dir_name); - /* Try $HOME/tmp */ - if (!dd) - { - char *home = getenv("HOME"); - if (home && home[0]) - { - home = concat_path_file(home, "tmp"); - /*mkdir(home, 0777); - do we want this? */ - dd = try_dd_create(home, dir_name); - free(home); - } - } -//TODO: try user's home dir obtained by getpwuid(getuid())? - /* Try /tmp */ - if (!dd) - dd = try_dd_create("/tmp", dir_name); - } - if (!dd) - return NULL; - - GHashTableIter iter; - char *name; - struct problem_item *value; - g_hash_table_iter_init(&iter, problem_data); - while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value)) - { - if (name[0] == '.' || strchr(name, '/')) - { - error_msg("Problem data field name contains disallowed chars: '%s'", name); - goto next; - } - -//FIXME: what to do with CD_FLAG_BINs?? - if (value->flags & CD_FLAG_BIN) - goto next; - - dd_save_text(dd, name, value->content); - next: ; - } - - return dd; -} diff --git a/libreport/src/lib/daemon_is_ok.c b/libreport/src/lib/daemon_is_ok.c deleted file mode 100644 index b4856b14..00000000 --- a/libreport/src/lib/daemon_is_ok.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (C) 2009 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "libreport.h" - -int daemon_is_ok() -{ - int fd = open(VAR_RUN"/abrtd.pid", O_RDONLY); - if (fd < 0) - { - return 0; - } - - char pid[sizeof(pid_t)*3 + 2]; - int len = read(fd, pid, sizeof(pid)-1); - close(fd); - if (len <= 0) - return 0; - - pid[len] = '\0'; - *strchrnul(pid, '\n') = '\0'; - /* paranoia: we don't want to check /proc//stat or /proc///stat */ - if (pid[0] == '\0' || pid[0] == '/') - return 0; - - char path[sizeof("/proc/%s/stat") + sizeof(pid)]; - sprintf(path, "/proc/%s/stat", pid); - struct stat sb; - if (stat(path, &sb) == -1) - { - return 0; - } - - /* TODO: maybe readlink /proc/PID/exe and check that it is "xxx/abrt"? */ - - return 1; -} diff --git a/libreport/src/lib/dirsize.c b/libreport/src/lib/dirsize.c deleted file mode 100644 index 88733ae0..00000000 --- a/libreport/src/lib/dirsize.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) - Copyright (C) 2009 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "libreport.h" - -double get_dirsize(const char *pPath) -{ - DIR *dp = opendir(pPath); - if (dp == NULL) - return 0; - - struct dirent *ep; - struct stat statbuf; - double size = 0; - while ((ep = readdir(dp)) != NULL) - { - if (dot_or_dotdot(ep->d_name)) - continue; - char *dname = concat_path_file(pPath, ep->d_name); - if (lstat(dname, &statbuf) != 0) - { - free(dname); - continue; - } - if (S_ISDIR(statbuf.st_mode)) - { - size += get_dirsize(dname); - } - else if (S_ISREG(statbuf.st_mode)) - { - size += statbuf.st_size; - } - free(dname); - } - closedir(dp); - return size; -} - -double get_dirsize_find_largest_dir( - const char *pPath, - char **worst_dir, - const char *excluded) -{ - if (worst_dir) - *worst_dir = NULL; - - DIR *dp = opendir(pPath); - if (dp == NULL) - return 0; - - struct dirent *ep; - struct stat statbuf; - double size = 0; - double maxsz = 0; - while ((ep = readdir(dp)) != NULL) - { - if (dot_or_dotdot(ep->d_name)) - continue; - char *dname = concat_path_file(pPath, ep->d_name); - if (lstat(dname, &statbuf) != 0) - { - free(dname); - continue; - } - if (S_ISDIR(statbuf.st_mode)) - { - double sz = get_dirsize(dname); - size += sz; - - if (worst_dir && (!excluded || strcmp(excluded, ep->d_name) != 0)) - { - /* Calculate "weighted" size and age - * w = sz_kbytes * age_mins */ - sz /= 1024; - long age = (time(NULL) - statbuf.st_mtime) / 60; - if (age > 0) - sz *= age; - - if (sz > maxsz) - { - maxsz = sz; - free(*worst_dir); - *worst_dir = xstrdup(ep->d_name); - } - } - } - else if (S_ISREG(statbuf.st_mode)) - { - size += statbuf.st_size; - } - free(dname); - } - closedir(dp); - return size; -} diff --git a/libreport/src/lib/dump_dir.c b/libreport/src/lib/dump_dir.c deleted file mode 100644 index 8891f911..00000000 --- a/libreport/src/lib/dump_dir.c +++ /dev/null @@ -1,839 +0,0 @@ -/* - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include -#include "libreport.h" -#include "strbuf.h" - -// Locking logic: -// -// The directory is locked by creating a symlink named .lock inside it, -// whose value (where it "points to") is the pid of locking process. -// We use symlink, not an ordinary file, because symlink creation -// is an atomic operation. -// -// There are two cases where after .lock creation, we might discover -// that directory is not really free: -// * another process just created new directory, but didn't manage -// to lock it before us. -// * another process is deleting the directory, and we managed to sneak in -// and create .lock after it deleted all files (including .lock) -// but before it rmdir'ed the empty directory. -// -// Both these cases are detected by the fact that file named "time" -// is not present (it must be present in any valid dump dir). -// If after locking the dir we don't see time file, we remove the lock -// at once and back off. What happens in concurrent processes -// we interfered with? -// * "create new dump dir" process just re-tries locking. -// * "delete dump dir" process just retries rmdir. -// -// There is another case when we don't find time file: -// when the directory is not really a *dump* dir - user gave us -// an ordinary directory name by mistake. -// We detect it by bailing out of "lock, check time file; sleep -// and retry if it doesn't exist" loop using a counter. -// -// To make locking work reliably, it's important to set timeouts -// correctly. For example, dd_create should retry locking -// its newly-created directory much faster than dd_opendir -// tries to lock the directory it tries to open. - - -// How long to sleep between "symlink fails with EEXIST, -// readlink fails with ENOENT" tries. Someone just unlocked the dir. -// We never bail out in this case, we retry forever. -// The value can be really small: -#define SYMLINK_RETRY_USLEEP (10*1000) - -// How long to sleep when lock file with valid pid is seen by dd_opendir -// (we are waiting for other process to unlock or die): -#define WAIT_FOR_OTHER_PROCESS_USLEEP (500*1000) - -// How long to sleep when lock file with valid pid is seen by dd_create -// (some idiot jumped the gun and locked the dir we just created). -// Must not be the same as WAIT_FOR_OTHER_PROCESS_USLEEP (we depend on this) -// and should be small (we have the priority in locking, this is OUR dir): -#define CREATE_LOCK_USLEEP (10*1000) - -// How long to sleep after we locked a dir, found no time file -// (either we are racing with someone, or it's not a dump dir) -// and unlocked it; -// and after how many tries to give up and declare it's not a dump dir: -#define NO_TIME_FILE_USLEEP (50*1000) -#define NO_TIME_FILE_COUNT 10 - -// How long to sleep after we unlocked an empty dir, but then rmdir failed -// (some idiot jumped the gun and locked the dir we are deleting); -// and after how many tries to give up: -#define RMDIR_FAIL_USLEEP (10*1000) -#define RMDIR_FAIL_COUNT 50 - - -static char *load_text_file(const char *path, unsigned flags); - -static bool isdigit_str(const char *str) -{ - do - { - if (*str < '0' || *str > '9') return false; - str++; - } while (*str); - return true; -} - -static bool exist_file_dir(const char *path) -{ - struct stat buf; - if (stat(path, &buf) == 0) - { - if (S_ISDIR(buf.st_mode) || S_ISREG(buf.st_mode)) - { - return true; - } - } - return false; -} - -/* Return values: - * -1: error (in this case, errno is 0 if error message is already logged) - * 0: failed to lock (someone else has it locked) - * 1: success - */ -static int get_and_set_lock(const char* lock_file, const char* pid) -{ - while (symlink(pid, lock_file) != 0) - { - if (errno != EEXIST) - { - if (errno != ENOENT && errno != ENOTDIR && errno != EACCES) - { - perror_msg("Can't create lock file '%s'", lock_file); - errno = 0; - } - return -1; - } - - char pid_buf[sizeof(pid_t)*3 + 4]; - ssize_t r = readlink(lock_file, pid_buf, sizeof(pid_buf) - 1); - if (r < 0) - { - if (errno == ENOENT) - { - /* Looks like lock_file was deleted */ - usleep(SYMLINK_RETRY_USLEEP); /* avoid CPU eating loop */ - continue; - } - perror_msg("Can't read lock file '%s'", lock_file); - errno = 0; - return -1; - } - pid_buf[r] = '\0'; - - if (strcmp(pid_buf, pid) == 0) - { - log("Lock file '%s' is already locked by us", lock_file); - return 0; - } - if (isdigit_str(pid_buf)) - { - char pid_str[sizeof("/proc/") + sizeof(pid_buf)]; - sprintf(pid_str, "/proc/%s", pid_buf); - if (access(pid_str, F_OK) == 0) - { - log("Lock file '%s' is locked by process %s", lock_file, pid_buf); - return 0; - } - log("Lock file '%s' was locked by process %s, but it crashed?", lock_file, pid_buf); - } - /* The file may be deleted by now by other process. Ignore ENOENT */ - if (unlink(lock_file) != 0 && errno != ENOENT) - { - perror_msg("Can't remove stale lock file '%s'", lock_file); - errno = 0; - return -1; - } - } - - VERB1 log("Locked '%s'", lock_file); - return 1; -} - -static int dd_lock(struct dump_dir *dd, unsigned sleep_usec, int flags) -{ - if (dd->locked) - error_msg_and_die("Locking bug on '%s'", dd->dd_dirname); - - char pid_buf[sizeof(long)*3 + 2]; - sprintf(pid_buf, "%lu", (long)getpid()); - - unsigned dirname_len = strlen(dd->dd_dirname); - char lock_buf[dirname_len + sizeof("/.lock")]; - strcpy(lock_buf, dd->dd_dirname); - strcpy(lock_buf + dirname_len, "/.lock"); - - unsigned count = NO_TIME_FILE_COUNT; - retry: - while (1) - { - int r = get_and_set_lock(lock_buf, pid_buf); - if (r < 0) - return r; /* error */ - if (r > 0) - break; /* locked successfully */ - /* Other process has the lock, wait for it to go away */ - usleep(sleep_usec); - } - - /* Are we called by dd_opendir (as opposed to dd_create)? */ - if (sleep_usec == WAIT_FOR_OTHER_PROCESS_USLEEP) /* yes */ - { - strcpy(lock_buf + dirname_len, "/time"); - if (access(lock_buf, F_OK) != 0) - { - /* time file doesn't exist. We managed to lock the directory - * which was just created by somebody else, or is almost deleted - * by delete_file_dir. - * Unlock and back off. - */ - strcpy(lock_buf + dirname_len, "/.lock"); - xunlink(lock_buf); - VERB1 log("Unlocked '%s' (no time file)", lock_buf); - if (--count == 0) - { - errno = EISDIR; /* "this is an ordinary dir, not dump dir" */ - return -1; - } - usleep(NO_TIME_FILE_USLEEP); - goto retry; - } - } - - dd->locked = true; - return 0; -} - -static void dd_unlock(struct dump_dir *dd) -{ - if (dd->locked) - { - dd->locked = 0; - - unsigned dirname_len = strlen(dd->dd_dirname); - char lock_buf[dirname_len + sizeof("/.lock")]; - strcpy(lock_buf, dd->dd_dirname); - strcpy(lock_buf + dirname_len, "/.lock"); - xunlink(lock_buf); - - VERB1 log("Unlocked '%s'", lock_buf); - } -} - -static inline struct dump_dir *dd_init(void) -{ - return (struct dump_dir*)xzalloc(sizeof(struct dump_dir)); -} - -int dd_exist(struct dump_dir *dd, const char *path) -{ - char *full_path = concat_path_file(dd->dd_dirname, path); - int ret = exist_file_dir(full_path); - free(full_path); - return ret; -} - -void dd_close(struct dump_dir *dd) -{ - if (!dd) - return; - - dd_unlock(dd); - if (dd->next_dir) - { - closedir(dd->next_dir); - /* free(dd->next_dir); - WRONG! */ - } - - free(dd->dd_dirname); - free(dd); -} - -static char* rm_trailing_slashes(const char *dir) -{ - unsigned len = strlen(dir); - while (len != 0 && dir[len-1] == '/') - len--; - return xstrndup(dir, len); -} - -struct dump_dir *dd_opendir(const char *dir, int flags) -{ - struct dump_dir *dd = dd_init(); - - dir = dd->dd_dirname = rm_trailing_slashes(dir); - - struct stat stat_buf; - stat(dir, &stat_buf); - /* & 0666 should remove the executable bit */ - dd->mode = (stat_buf.st_mode & 0666); - - errno = 0; - if (dd_lock(dd, WAIT_FOR_OTHER_PROCESS_USLEEP, flags) < 0) - { - if ((flags & DD_OPEN_READONLY) && errno == EACCES) - { - /* Directory is not writable. If it seems to be readable, - * return "read only" dd, not NULL */ - if (stat(dir, &stat_buf) == 0 - && S_ISDIR(stat_buf.st_mode) - && access(dir, R_OK) == 0 - ) { - return dd; - } - } - if (errno == EISDIR) - { - /* EISDIR: dd_lock can lock the dir, but it sees no time file there, - * even after it retried many times. It must be an ordinary directory! - * - * Without this check, e.g. abrt-action-print happily prints any current - * directory when run without arguments, because its option -d DIR - * defaults to "."! - */ - error_msg("'%s' is not a dump directory", dir); - } - else if (errno == ENOENT || errno == ENOTDIR) - { - if (!(flags & DD_FAIL_QUIETLY_ENOENT)) - error_msg("'%s' does not exist", dir); - } - else - { - if (!(flags & DD_FAIL_QUIETLY_EACCES)) - perror_msg("Can't access '%s'", dir); - } - dd_close(dd); - return NULL; - } - - dd->dd_uid = (uid_t)-1L; - dd->dd_gid = (gid_t)-1L; - if (geteuid() == 0) - { - /* In case caller would want to create more files, he'll need uid:gid */ - struct stat stat_buf; - if (stat(dir, &stat_buf) != 0 || !S_ISDIR(stat_buf.st_mode)) - { - error_msg("Can't stat '%s', or it is not a directory", dir); - dd_close(dd); - return NULL; - } - dd->dd_uid = stat_buf.st_uid; - dd->dd_gid = stat_buf.st_gid; - } - - return dd; -} - -/* Create a fresh empty debug dump dir. - * - * Security: we should not allow users to write new files or write - * into existing ones, but they should be able to read them. - * - * @param uid - * Crashed application's User Id - * - * We currently have only three callers: - * kernel oops hook: uid -> not saved, so everyone can steal and work with it - * this hook runs under 0:0 - * ccpp hook: uid=uid of crashed user's binary - * this hook runs under 0:0 - * python hook: uid=uid of crashed user's script - * this hook runs under abrt:gid - * - * Currently, we set dir's gid to passwd(uid)->pw_gid parameter, and we set uid to - * abrt's user id. We do not allow write access to group. - */ -struct dump_dir *dd_create(const char *dir, uid_t uid, mode_t mode) -{ - /* a little trick to copy read bits from file mode to exec bit of dir mode*/ - mode_t dir_mode = mode | ((mode & 0444) >> 2); - struct dump_dir *dd = dd_init(); - - dd->mode = mode; - - /* Unlike dd_opendir, can't use realpath: the directory doesn't exist yet, - * realpath will always return NULL. We don't really have to: - * dd_opendir(".") makes sense, dd_create(".") does not. - */ - dir = dd->dd_dirname = rm_trailing_slashes(dir); - - const char *last_component = strrchr(dir, '/'); - if (last_component) - last_component++; - else - last_component = dir; - if (dot_or_dotdot(last_component)) - { - /* dd_create("."), dd_create(".."), dd_create("dir/."), - * dd_create("dir/..") and similar are madness, refuse them. - */ - error_msg("Bad dir name '%s'", dir); - dd_close(dd); - return NULL; - } - - bool created_parents = false; - try_again: - /* Was creating it with mode 0700 and user as the owner, but this allows - * the user to replace any file in the directory, changing security-sensitive data - * (e.g. "uid", "analyzer", "executable") - */ - if (mkdir(dir, dir_mode) == -1) - { - int err = errno; - if (!created_parents && errno == ENOENT) - { - char *p = dd->dd_dirname + 1; - while ((p = strchr(p, '/')) != NULL) - { - *p = '\0'; - int r = (mkdir(dd->dd_dirname, 0755) == 0 || errno == EEXIST); - *p++ = '/'; - if (!r) - goto report_err; - } - created_parents = true; - goto try_again; - } - report_err: - errno = err; - perror_msg("Can't create directory '%s'", dir); - dd_close(dd); - return NULL; - } - - if (dd_lock(dd, CREATE_LOCK_USLEEP, /*flags:*/ 0) < 0) - { - dd_close(dd); - return NULL; - } - - /* mkdir's mode (above) can be affected by umask, fix it */ - if (chmod(dir, dir_mode) == -1) - { - perror_msg("can't change mode of '%s'", dir); - dd_close(dd); - return NULL; - } - - dd->dd_uid = (uid_t)-1L; - dd->dd_gid = (gid_t)-1L; - if (uid != (uid_t)-1L) - { - /* Get ABRT's user id */ - dd->dd_uid = 0; - struct passwd *pw = getpwnam("abrt"); - if (pw) - dd->dd_uid = pw->pw_uid; - else - error_msg("user 'abrt' does not exist, using uid 0"); - - /* Get crashed application's group id */ - /*dd->dd_gid = 0; - dd_init did this already */ - pw = getpwuid(uid); - if (pw) - dd->dd_gid = pw->pw_gid; - else - error_msg("User %lu does not exist, using gid 0", (long)uid); - - if (chown(dir, dd->dd_uid, dd->dd_gid) == -1) - { - perror_msg("can't change '%s' ownership to %lu:%lu", dir, - (long)dd->dd_uid, (long)dd->dd_gid); - } - } - - return dd; -} - -void dd_create_basic_files(struct dump_dir *dd, uid_t uid) -{ - char long_str[sizeof(long) * 3 + 2]; - - time_t t = time(NULL); - sprintf(long_str, "%lu", (long)t); - dd_save_text(dd, FILENAME_TIME, long_str); - - /* it doesn't make sense to create the uid file if uid == -1 */ - if (uid != (uid_t)-1L) - { - sprintf(long_str, "%li", (long)uid); - dd_save_text(dd, FILENAME_UID, long_str); - } - - struct utsname buf; - uname(&buf); /* never fails */ - dd_save_text(dd, FILENAME_KERNEL, buf.release); - dd_save_text(dd, FILENAME_ARCHITECTURE, buf.machine); - dd_save_text(dd, FILENAME_HOSTNAME, buf.nodename); - - char *release = load_text_file("/etc/system-release", - DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE); - if (!release) - release = load_text_file("/etc/redhat-release", /*flags:*/ 0); - dd_save_text(dd, FILENAME_OS_RELEASE, release); - free(release); -} - -void dd_sanitize_mode_and_owner(struct dump_dir *dd) -{ - /* Don't sanitize if we aren't run under root: - * we assume that during file creation (by whatever means, - * even by "hostname >file" in abrt_event.conf) - * normal umask-based mode setting takes care of correct mode, - * and uid:gid is, of course, set to user's uid and gid. - * - * For root operating on /var/spool/abrt/USERS_PROBLEM, this isn't true: - * "hostname >file", for example, would create file OWNED BY ROOT! - * This routine resets mode and uid:gid for all such files. - */ - if (dd->dd_uid == (uid_t)-1) - return; - - if (!dd->locked) - error_msg_and_die("dump_dir is not opened"); /* bug */ - - DIR *d = opendir(dd->dd_dirname); - if (!d) - return; - - struct dirent *dent; - while ((dent = readdir(d)) != NULL) - { - if (dent->d_name[0] == '.') /* ".lock", ".", ".."? skip */ - continue; - char *full_path = concat_path_file(dd->dd_dirname, dent->d_name); - struct stat statbuf; - if (lstat(full_path, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) - { - if ((statbuf.st_mode & 0777) != dd->mode) - chmod(full_path, dd->mode); - if (statbuf.st_uid != dd->dd_uid || statbuf.st_gid != dd->dd_gid) - { - if (chown(full_path, dd->dd_uid, dd->dd_gid) != 0) - { - perror_msg("can't change '%s' ownership to %lu:%lu", full_path, - (long)dd->dd_uid, (long)dd->dd_gid); - } - } - } - free(full_path); - } - closedir(d); -} - -static int delete_file_dir(const char *dir, bool skip_lock_file) -{ - DIR *d = opendir(dir); - if (!d) - { - /* The caller expects us to error out only if the directory - * still exists (not deleted). If directory - * *doesn't exist*, return 0 and clear errno. - */ - if (errno == ENOENT || errno == ENOTDIR) - { - errno = 0; - return 0; - } - return -1; - } - - bool unlink_lock_file = false; - struct dirent *dent; - while ((dent = readdir(d)) != NULL) - { - if (dot_or_dotdot(dent->d_name)) - continue; - if (skip_lock_file && strcmp(dent->d_name, ".lock") == 0) - { - unlink_lock_file = true; - continue; - } - char *full_path = concat_path_file(dir, dent->d_name); - if (unlink(full_path) == -1 && errno != ENOENT) - { - int err = 0; - if (errno == EISDIR) - { - errno = 0; - err = delete_file_dir(full_path, /*skip_lock_file:*/ false); - } - if (errno || err) - { - perror_msg("Can't remove '%s'", full_path); - free(full_path); - closedir(d); - return -1; - } - } - free(full_path); - } - closedir(d); - - /* Here we know for sure that all files/subdirs we found via readdir - * were deleted successfully. If rmdir below fails, we assume someone - * is racing with us and created a new file. - */ - - if (unlink_lock_file) - { - char *full_path = concat_path_file(dir, ".lock"); - xunlink(full_path); - free(full_path); - - unsigned cnt = RMDIR_FAIL_COUNT; - do { - if (rmdir(dir) == 0) - return 0; - /* Someone locked the dir after unlink, but before rmdir. - * This "someone" must be dd_lock(). - * It detects this (by seeing that there is no time file) - * and backs off at once. So we need to just retry rmdir, - * with minimal sleep. - */ - usleep(RMDIR_FAIL_USLEEP); - } while (--cnt != 0); - } - - int r = rmdir(dir); - if (r) - perror_msg("Can't remove directory '%s'", dir); - return r; -} - -int dd_delete(struct dump_dir *dd) -{ - int r = delete_file_dir(dd->dd_dirname, /*skip_lock_file:*/ true); - dd->locked = 0; /* delete_file_dir already removed .lock */ - dd_close(dd); - return r; -} - -static char *load_text_file(const char *path, unsigned flags) -{ - FILE *fp = fopen(path, "r"); - if (!fp) - { - if (!(flags & DD_FAIL_QUIETLY_ENOENT)) - perror_msg("Can't open file '%s'", path); - return (flags & DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE ? NULL : xstrdup("")); - } - - struct strbuf *buf_content = strbuf_new(); - int oneline = 0; - int ch; - while ((ch = fgetc(fp)) != EOF) - { -//TODO? \r -> \n? -//TODO? strip trailing spaces/tabs? - if (ch == '\n') - oneline = (oneline << 1) | 1; - if (ch == '\0') - ch = ' '; - if (isspace(ch) || ch >= ' ') /* used !iscntrl, but it failed on unicode */ - strbuf_append_char(buf_content, ch); - } - fclose(fp); - - char last = oneline != 0 ? buf_content->buf[buf_content->len - 1] : 0; - if (last == '\n') - { - /* If file contains exactly one '\n' and it is at the end, remove it. - * This enables users to use simple "echo blah >file" in order to create - * short string items in dump dirs. - */ - if (oneline == 1) - buf_content->buf[--buf_content->len] = '\0'; - } - else /* last != '\n' */ - { - /* Last line is unterminated, fix it */ - /* Cases: */ - /* oneline=0: "qwe" - DONT fix this! */ - /* oneline=1: "qwe\nrty" - two lines in fact */ - /* oneline>1: "qwe\nrty\uio" */ - if (oneline >= 1) - strbuf_append_char(buf_content, '\n'); - } - - return strbuf_free_nobuf(buf_content); -} - -static bool save_binary_file(const char *path, const char* data, unsigned size, uid_t uid, gid_t gid, mode_t mode) -{ - /* the mode is set by the caller, see dd_create() for security analysis */ - unlink(path); - int fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode); - if (fd < 0) - { - perror_msg("Can't open file '%s'", path); - return false; - } - - if (uid != (uid_t)-1L) - { - if (fchown(fd, uid, gid) == -1) - { - perror_msg("can't change '%s' ownership to %lu:%lu", path, (long)uid, (long)gid); - } - } - - unsigned r = full_write(fd, data, size); - close(fd); - if (r != size) - { - error_msg("Can't save file '%s'", path); - return false; - } - - return true; -} - -char* dd_load_text_ext(const struct dump_dir *dd, const char *name, unsigned flags) -{ -// if (!dd->locked) -// error_msg_and_die("dump_dir is not opened"); /* bug */ - - /* Compat with old abrt dumps. Remove in abrt-2.1 */ - if (strcmp(name, "release") == 0) - name = FILENAME_OS_RELEASE; - - char *full_path = concat_path_file(dd->dd_dirname, name); - char *ret = load_text_file(full_path, flags); - free(full_path); - - return ret; -} - -char* dd_load_text(const struct dump_dir *dd, const char *name) -{ - return dd_load_text_ext(dd, name, /*flags:*/ 0); -} - -void dd_save_text(struct dump_dir *dd, const char *name, const char *data) -{ - if (!dd->locked) - error_msg_and_die("dump_dir is not opened"); /* bug */ - - char *full_path = concat_path_file(dd->dd_dirname, name); - save_binary_file(full_path, data, strlen(data), dd->dd_uid, dd->dd_gid, dd->mode); - free(full_path); -} - -void dd_save_binary(struct dump_dir* dd, const char* name, const char* data, unsigned size) -{ - if (!dd->locked) - error_msg_and_die("dump_dir is not opened"); /* bug */ - - char *full_path = concat_path_file(dd->dd_dirname, name); - save_binary_file(full_path, data, size, dd->dd_uid, dd->dd_gid, dd->mode); - free(full_path); -} - -void add_reported_to(struct dump_dir *dd, const char *line) -{ - if (!dd->locked) - error_msg_and_die("dump_dir is not opened"); /* bug */ - - char *reported_to = dd_load_text_ext(dd, FILENAME_REPORTED_TO, DD_FAIL_QUIETLY_ENOENT | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE); - if (reported_to) - { - unsigned len_line = strlen(line); - char *p = reported_to; - while (*p) - { - if (strncmp(p, line, len_line) == 0 && (p[len_line] == '\n' || p[len_line] == '\0')) - goto ret; - p = strchrnul(p, '\n'); - if (!*p) - break; - p++; - } - if (p != reported_to && p[-1] != '\n') - reported_to = append_to_malloced_string(reported_to, "\n"); - reported_to = append_to_malloced_string(reported_to, line); - reported_to = append_to_malloced_string(reported_to, "\n"); - } - else - reported_to = xasprintf("%s\n", line); - dd_save_text(dd, FILENAME_REPORTED_TO, reported_to); - ret: - free(reported_to); -} - -DIR *dd_init_next_file(struct dump_dir *dd) -{ -// if (!dd->locked) -// error_msg_and_die("dump_dir is not opened"); /* bug */ - - if (dd->next_dir) - closedir(dd->next_dir); - - dd->next_dir = opendir(dd->dd_dirname); - if (!dd->next_dir) - { - error_msg("Can't open directory '%s'", dd->dd_dirname); - } - - return dd->next_dir; -} - -int dd_get_next_file(struct dump_dir *dd, char **short_name, char **full_name) -{ - if (dd->next_dir == NULL) - return 0; - - struct dirent *dent; - while ((dent = readdir(dd->next_dir)) != NULL) - { - if (is_regular_file(dent, dd->dd_dirname)) - { - if (short_name) - *short_name = xstrdup(dent->d_name); - if (full_name) - *full_name = concat_path_file(dd->dd_dirname, dent->d_name); - return 1; - } - } - - closedir(dd->next_dir); - dd->next_dir = NULL; - return 0; -} - -/* Utility function */ -void delete_dump_dir(const char *dirname) -{ - struct dump_dir *dd = dd_opendir(dirname, /*flags:*/ 0); - if (dd) - { - dd_delete(dd); - } -} diff --git a/libreport/src/lib/encbase64.c b/libreport/src/lib/encbase64.c deleted file mode 100644 index 9ba11e6c..00000000 --- a/libreport/src/lib/encbase64.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2006 Rob Landley - * - * Copyright (C) 2010 ABRT team - * Copyright (C) 2010 RedHat 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 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#include "libreport.h" /* xmalloc */ - -/* Conversion table for base 64 */ -static const char tbl_base64[65 /*+ 2*/] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/', - '=' /* termination character */, - // '\n', '\0' /* needed for uudecode.c */ -}; - -/* Conversion table for uuencode -const char tbl_uuencode[65] ALIGN1 = { - '`', '!', '"', '#', '$', '%', '&', '\'', - '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', ':', ';', '<', '=', '>', '?', - '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', - '`' -}; -*/ - -/* - * Encode bytes at S of length LENGTH. - * Result will be 0-terminated, and must point to a writable - * buffer of at least 1+BASE64_LENGTH(length) bytes, - * where BASE64_LENGTH(len) = 4 * ((LENGTH + 2) / 3) - */ -static void encode_64bit(char *p, const void *src, int length, const char *tbl) -{ - const unsigned char *s = (const unsigned char *)src; - - /* Transform the 3x8 bits to 4x6 bits */ - while (length > 0) { - unsigned s1, s2; - - /* Are s[1], s[2] valid or should be assumed 0? */ - s1 = s2 = 0; - length -= 3; /* can be >=0, -1, -2 */ - if (length >= -1) { - s1 = s[1]; - if (length >= 0) - s2 = s[2]; - } - *p++ = tbl[s[0] >> 2]; - *p++ = tbl[((s[0] & 3) << 4) + (s1 >> 4)]; - *p++ = tbl[((s1 & 0xf) << 2) + (s2 >> 6)]; - *p++ = tbl[s2 & 0x3f]; - s += 3; - } - /* Zero-terminate */ - *p = '\0'; - /* If length is -2 or -1, pad last char or two */ - while (length) { - *--p = tbl[64]; - length++; - } -} - -char *encode_base64(const void *src, int length) -{ - char *dst = (char *)xmalloc(4 * ((length + 2) / 3) + 1); - encode_64bit(dst, src, length, tbl_base64); - return dst; -} diff --git a/libreport/src/lib/event_config.c b/libreport/src/lib/event_config.c deleted file mode 100644 index 35ed8d36..00000000 --- a/libreport/src/lib/event_config.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - Copyright (C) 2011 ABRT Team - Copyright (C) 2011 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "libreport.h" - -GHashTable *g_event_config_list; -static GHashTable *g_event_config_symlinks; - -event_option_t *new_event_option(void) -{ - return xzalloc(sizeof(event_option_t)); -} - -event_config_t *new_event_config(void) -{ - return xzalloc(sizeof(event_config_t)); -} - -void free_event_option(event_option_t *p) -{ - if (!p) - return; - free(p->eo_name); - free(p->eo_value); - free(p->eo_label); - free(p->eo_note_html); - //free(p->eo_description); - //free(p->eo_allowed_value); - free(p); -} - -void free_event_config(event_config_t *p) -{ - if (!p) - return; - - free(p->screen_name); - free(p->description); - free(p->long_descr); - free(p->ec_creates_items); - free(p->ec_requires_items); - free(p->ec_exclude_items_by_default); - free(p->ec_include_items_by_default); - free(p->ec_exclude_items_always); - GList *opt; - for (opt = p->options; opt; opt = opt->next) - free_event_option(opt->data); - g_list_free(p->options); - - free(p); -} - - -static int cmp_event_option_name_with_string(gconstpointer a, gconstpointer b) -{ - const event_option_t *evopt = a; - return !evopt->eo_name || strcmp(evopt->eo_name, (char *)b) != 0; -} - -event_option_t *get_event_option_from_list(const char *name, GList *options) -{ - GList *elem = g_list_find_custom(options, name, &cmp_event_option_name_with_string); - if (elem) - return (event_option_t *)elem->data; - return NULL; -} - -static void load_config_files(const char *dir_path) -{ - DIR *dir; - struct dirent *dent; - - /* Load .conf files */ - dir = opendir(dir_path); - if (!dir) - return; - while ((dent = readdir(dir)) != NULL) - { - char *ext = strrchr(dent->d_name, '.'); - if (!ext) - continue; - if (strcmp(ext + 1, "conf") != 0) - continue; - - char *fullname = concat_path_file(dir_path, dent->d_name); - - *ext = '\0'; - event_config_t *event_config = get_event_config(dent->d_name); - bool new_config = (!event_config); - if (new_config) - event_config = new_event_config(); - - map_string_h *keys_and_values = new_map_string(); - - load_conf_file(fullname, keys_and_values, /*skipKeysWithoutValue:*/ false); - free(fullname); - - /* Insert or replace every key/value from keys_and_values to event_config->option */ - GHashTableIter iter; - char *name; - char *value; - g_hash_table_iter_init(&iter, keys_and_values); - while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value)) - { - event_option_t *opt; - GList *elem = g_list_find_custom(event_config->options, name, - cmp_event_option_name_with_string); - if (elem) - { - opt = elem->data; - // log("conf: replacing '%s' value:'%s'->'%s'", name, opt->value, value); - free(opt->eo_value); - } - else - { - // log("conf: new value %s='%s'", name, value); - opt = new_event_option(); - opt->eo_name = xstrdup(name); - } - opt->eo_value = xstrdup(value); - if (!elem) - event_config->options = g_list_append(event_config->options, opt); - } - - free_map_string(keys_and_values); - - if (new_config) - g_hash_table_replace(g_event_config_list, xstrdup(dent->d_name), event_config); - } - closedir(dir); -} - -/* (Re)loads data from /etc/abrt/events/foo.{xml,conf} and ~/.abrt/events/foo.conf */ -void load_event_config_data(void) -{ - free_event_config_data(); - - if (!g_event_config_list) - g_event_config_list = g_hash_table_new_full( - /*hash_func*/ g_str_hash, - /*key_equal_func:*/ g_str_equal, - /*key_destroy_func:*/ free, - /*value_destroy_func:*/ (GDestroyNotify) free_event_config - ); - if (!g_event_config_symlinks) - g_event_config_symlinks = g_hash_table_new_full( - /*hash_func*/ g_str_hash, - /*key_equal_func:*/ g_str_equal, - /*key_destroy_func:*/ free, - /*value_destroy_func:*/ free - ); - - DIR *dir; - struct dirent *dent; - - /* Load .xml files */ - dir = opendir(EVENTS_DIR); - if (!dir) - return; - while ((dent = readdir(dir)) != NULL) - { - char *ext = strrchr(dent->d_name, '.'); - if (!ext) - continue; - if (strcmp(ext + 1, "xml") != 0) - continue; - - char *fullname = concat_path_file(EVENTS_DIR, dent->d_name); - *ext = '\0'; - - struct stat buf; - if (0 != lstat(fullname, &buf)) - continue; - if (S_ISLNK(buf.st_mode)) - { - GError *error = NULL; - gchar *link = g_file_read_link(fullname, &error); - if (error != NULL) - error_msg_and_die("Error reading symlink '%s': %s", fullname, error->message); - - gchar *target = g_path_get_basename(link); - char *ext = strrchr(target, '.'); - if (!ext || 0 != strcmp(ext + 1, "xml")) - error_msg_and_die("Invalid event symlink '%s': expected it to" - " point to another xml file", fullname); - *ext = '\0'; - g_hash_table_replace(g_event_config_symlinks, xstrdup(dent->d_name), target); - g_free(link); - /* don't free target, it is owned by the hash table now */ - continue; - } - - event_config_t *event_config = get_event_config(dent->d_name); - bool new_config = (!event_config); - if (new_config) - event_config = new_event_config(); - - load_event_description_from_file(event_config, fullname); - free(fullname); - - if (new_config) - g_hash_table_replace(g_event_config_list, xstrdup(dent->d_name), event_config); - } - closedir(dir); - - load_config_files(EVENTS_DIR); - - char *HOME = getenv("HOME"); - if (!HOME || !HOME[0]) - return; - HOME = concat_path_file(HOME, ".abrt/events"); - load_config_files(HOME); - free(HOME); -} - -/* Frees all loaded data */ -void free_event_config_data(void) -{ - if (g_event_config_list) - { - g_hash_table_destroy(g_event_config_list); - g_event_config_list = NULL; - } - if (g_event_config_symlinks) - { - g_hash_table_destroy(g_event_config_symlinks); - g_event_config_symlinks = NULL; - } -} - -event_config_t *get_event_config(const char *name) -{ - if (!g_event_config_list) - return NULL; - if (g_event_config_symlinks) - { - char *link = g_hash_table_lookup(g_event_config_symlinks, name); - if (link) - name = link; - } - return g_hash_table_lookup(g_event_config_list, name); -} - -GList *export_event_config(const char *event_name) -{ - GList *env_list = NULL; - - event_config_t *config = get_event_config(event_name); - if (config) - { - GList *lopt; - for (lopt = config->options; lopt; lopt = lopt->next) - { - event_option_t *opt = lopt->data; - if (!opt->eo_value) - continue; - char *var_val = xasprintf("%s=%s", opt->eo_name, opt->eo_value); - VERB3 log("Exporting '%s'", var_val); - env_list = g_list_prepend(env_list, var_val); - putenv(var_val); - } - } - - return env_list; -} - -void unexport_event_config(GList *env_list) -{ - while (env_list) - { - char *var_val = env_list->data; - VERB3 log("Unexporting '%s'", var_val); - safe_unsetenv(var_val); - env_list = g_list_remove(env_list, var_val); - free(var_val); - } -} - -/* return NULL if successful otherwise appropriate error message */ -static char *validate_event_option(event_option_t *opt) -{ - if (!opt->eo_allow_empty && (!opt->eo_value || !opt->eo_value[0])) - return xstrdup(_("Missing mandatory value")); - - /* if value is NULL and allow-empty yes than it doesn't make sence to check it */ - if (!opt->eo_value) - return NULL; - - const gchar *s = NULL; - if (!g_utf8_validate(opt->eo_value, -1, &s)) - return xasprintf(_("Invalid utf8 character '%c'"), *s); - - switch (opt->eo_type) { - case OPTION_TYPE_TEXT: - case OPTION_TYPE_PASSWORD: - break; - case OPTION_TYPE_NUMBER: - { - char *endptr; - errno = 0; - long r = strtol(opt->eo_value, &endptr, 10); - (void) r; - if (errno != 0 || endptr == opt->eo_value || *endptr != '\0') - return xasprintf(_("Invalid number '%s'"), opt->eo_value); - - break; - } - case OPTION_TYPE_BOOL: - if (strcmp(opt->eo_value, "yes") != 0 - && strcmp(opt->eo_value, "no") != 0 - && strcmp(opt->eo_value, "on") != 0 - && strcmp(opt->eo_value, "off") != 0 - && strcmp(opt->eo_value, "1") != 0 - && strcmp(opt->eo_value, "0") != 0) - { - return xasprintf(_("Invalid boolean value '%s'"), opt->eo_value); - } - break; - case OPTION_TYPE_HINT_HTML: - return NULL; - default: - return xstrdup(_("Unsupported option type")); - }; - - return NULL; -} - -GHashTable *validate_event(const char *event_name) -{ - event_config_t *config = get_event_config(event_name); - if (!config) - return NULL; - - GHashTable *errors = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); - GList *li; - - for (li = config->options; li; li = li->next) - { - event_option_t *opt = (event_option_t *)li->data; - char *err = validate_event_option(opt); - if (err) - g_hash_table_insert(errors, xstrdup(opt->eo_name), err); - } - - if (g_hash_table_size(errors)) - return errors; - - g_hash_table_destroy(errors); - - return NULL; -} diff --git a/libreport/src/lib/event_xml_parser.c b/libreport/src/lib/event_xml_parser.c deleted file mode 100644 index 4a2e4493..00000000 --- a/libreport/src/lib/event_xml_parser.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - Copyright (C) 2011 ABRT Team - Copyright (C) 2011 RedHat 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 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "libreport.h" -#include "event_config.h" - -#define EVENT_ELEMENT "event" -#define LABEL_ELEMENT "label" -#define DESCRIPTION_ELEMENT "description" -#define LONG_DESCR_ELEMENT "long-description" -#define ALLOW_EMPTY_ELEMENT "allow-empty" -#define NOTE_HTML_ELEMENT "note-html" -#define CREATES_ELEMENT "creates-items" -#define OPTION_ELEMENT "option" -//#define ACTION_ELEMENT "action" -#define NAME_ELEMENT "name" -#define DEFAULT_VALUE_ELEMENT "default-value" - -#define REQUIRES_ELEMENT "requires-items" -#define EXCL_BY_DEFAULT_ELEMENT "exclude-items-by-default" -#define INCL_BY_DEFAULT_ELEMENT "include-items-by-default" -#define EXCL_ALWAYS_ELEMENT "exclude-items-always" -#define EXCL_BINARY_ELEMENT "exclude-binary-items" - - -struct my_parse_data -{ - event_config_t *event_config; - event_option_t *cur_option; - const char *cur_locale; - char *attribute_lang; -}; - -static const char *const option_types[] = -{ - [OPTION_TYPE_TEXT ] = "text", - [OPTION_TYPE_BOOL ] = "bool", - [OPTION_TYPE_PASSWORD ] = "password", - [OPTION_TYPE_NUMBER ] = "number", - [OPTION_TYPE_HINT_HTML] = "hint-html", - [OPTION_TYPE_INVALID ] = NULL -}; - -// Return xml:lang value for if value matches current locale, -// "" if foo has no xml:lang attribute at all, -// else (if xml:lang is for some other locale) return NULL -// -static char *get_element_lang(struct my_parse_data *parse_data, const gchar **att_names, const gchar **att_values) -{ - char *short_locale_end = strchr(parse_data->cur_locale, '_'); - VERB3 log("locale: %s", parse_data->cur_locale); - int i; - for (i = 0; att_names[i] != NULL; ++i) - { - VERB3 log("attr: %s:%s", att_names[i], att_values[i]); - if (strcmp(att_names[i], "xml:lang") == 0) - { - if (strcmp(att_values[i], parse_data->cur_locale) == 0) - { - VERB3 log("found translation for: %s", parse_data->cur_locale); - return xstrdup(att_values[i]); - } - - /* try to match shorter locale - * e.g: "cs" with cs_CZ - */ - if (short_locale_end - && strncmp(att_values[i], parse_data->cur_locale, short_locale_end - parse_data->cur_locale) == 0 - ) { - VERB3 log("found translation for shortlocale: %s", parse_data->cur_locale); - return xstrndup(att_values[i], short_locale_end - parse_data->cur_locale); - } - } - } - /* if the element has no attribute then it's a default non-localized value */ - if (i == 0) - return xstrdup(""); - /* if the element is in different language than the current locale */ - return NULL; -} - -static int cmp_event_option_name_with_string(gconstpointer a, gconstpointer b) -{ - const event_option_t *evopt = a; - /* "When it is not a match?" */ - return !evopt->eo_name || strcmp(evopt->eo_name, (char *)b) != 0; -} - -static void consume_cur_option(struct my_parse_data *parse_data) -{ - event_option_t *opt = parse_data->cur_option; - if (!opt) - return; - parse_data->cur_option = NULL; - - event_config_t *event_config = parse_data->event_config; - - /* Example of "nameless" option: