On 03/22/2012 05:24 PM, Nikola Pajkovsky wrote:
Jiri Moskovcak<[email protected]> writes:
+static void handle_method_call(GDBusConnection *connection,
+ const gchar *caller,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ reset_timeout();
+ uid_t caller_uid;
+ GVariant *response;
+
+ if (g_strcmp0(method_name, "GetProblems") == 0)
+ {
+
^ pointless new line
- fixed
+ caller_uid = get_caller_uid(connection, invocation, caller);
+
+ if (caller_uid == (uid_t) -1)
+ return;
exctract from all parts of if () caller_uid and check before if's
- moved to the top
+ }
+
^ pointless new line before every *else if*
- it's there for a reason because those else if are quite separate
blocks, so I want to make it more obvious
+ else if (g_strcmp0(method_name, "GetAllProblems") == 0)
+ {
+
dito
+ }
+
+ else if (g_strcmp0(method_name, "ChownProblemDir") == 0)
+ {
...
...
...
+ if (stat(problem_dir,&statbuf) == 0&& S_ISDIR(statbuf.st_mode))
+ {
+ if (caller_uid == 0 || uid_in_group(caller_uid, statbuf.st_gid))
//caller seems to be in group with access to this dir, so no action needed
+ {
+ //return ok
remove comment
+ VERB1 log("caller has access to the requested directory %s",
problem_dir);
+ g_dbus_method_invocation_return_value(invocation, NULL);
+ dd_close(dd);
+ return;
+ //free something?
dito comment
- fixed
+ }
+
+ }
+ else
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation,
+
"org.freedesktop.problems.StatFailure",
+ strerror(errno));
+ dd_close(dd);
+ return;
+ }
+ pwd = getpwuid(caller_uid);
+ if (pwd)
+ {
+ errno = 0;
+ chown_res = chown(problem_dir, statbuf.st_uid, pwd->pw_gid);
you don't have to set errno to 0, because if chown on success return
0. On error -1 errno is set.
+ dd_init_next_file(dd);
+ char *short_name, *full_name;
+ while (chown_res == 0&&
dd_get_next_file(dd,&short_name,&full_name))
+ {
+ VERB3 log("chowning %s", full_name);
+ chown_res = chown(full_name, statbuf.st_uid, pwd->pw_gid);
+ }
+
+ if (chown_res != 0)
according to man-pages, you should have to check -1
- according to man pages 0 means success, so anything != 0 isn't OK
+ g_dbus_method_invocation_return_dbus_error(invocation,
+
"org.freedesktop.problems.ChownError",
+ strerror(errno));
+
+ g_dbus_method_invocation_return_value(invocation, NULL);
+ dd_close(dd);
+ return;
+ }
+ VERB3 log("shouldn't get here");
+ dd_close(dd);
+ }
+
+ else if (g_strcmp0(method_name, "GetInfo") == 0)
+ {
+ VERB1 log("GetInfo");
+
+ const gchar *problem_dir;
+ g_variant_get(parameters, "(&s)",&problem_dir);
+
+ GVariantBuilder *builder;
+
+ struct stat statbuf;
+ errno = 0;
do not reset errno unless it's needed
On success, zero is returned. On error, -1 is returned, and errno is
set appropriately.
- I prefer to set it to 0 before using it, it feels "safer"
+ if (stat(problem_dir,&statbuf) != 0)
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation,
+
"org.freedesktop.problems.GetInfoError",
+ strerror(errno));
+ return;
+ }
+
+
+ caller_uid = get_caller_uid(connection, invocation, caller);
+
+ if (caller_uid == (uid_t) -1)
+ return;
+
+ if (!uid_in_group(caller_uid, statbuf.st_gid))
+ {
+ if (polkit_check_authorization_dname(caller,
"org.freedesktop.problems.getall") != PolkitYes)
+ {
+ VERB1 log("not authorized");
+ g_dbus_method_invocation_return_dbus_error(invocation,
+
"org.freedesktop.problems.AuthFailure",
+ "Not Authorized");
^^^ not translatable
some others are not translatable also
- fixed
+ return;
+ }
+ }
+
+ struct dump_dir *dd = dd_opendir(problem_dir, DD_OPEN_READONLY |
DD_FAIL_QUIETLY_EACCES);
+ if (!dd)
+ {
+ char *error_msg = g_strdup_printf(_("%s is not a valid problem
directory"), problem_dir);
+ g_dbus_method_invocation_return_dbus_error(invocation,
+
"org.freedesktop.problems.GetInfo",
+ error_msg);
+ free(error_msg);
+ }
here is a bug, when dd is NULL then you print msg and continue to
dd_load_text(dd... to have to exit here.
- fixed
+ builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_add (builder, "{ss}", g_strdup(FILENAME_TIME),
dd_load_text(dd, FILENAME_TIME));
+ g_variant_builder_add (builder, "{ss}", g_strdup(FILENAME_REASON),
dd_load_text(dd, FILENAME_REASON));
+ char *not_reportable_reason = dd_load_text_ext(dd,
FILENAME_NOT_REPORTABLE, 0
+ |
DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+ | DD_FAIL_QUIETLY_ENOENT
+ |
DD_FAIL_QUIETLY_EACCES);
+ if (not_reportable_reason)
+ g_variant_builder_add (builder, "{ss}",
g_strdup(FILENAME_NOT_REPORTABLE), dd_load_text_ext(dd, FILENAME_NOT_REPORTABLE, 0
+
| DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+
| DD_FAIL_QUIETLY_ENOENT
+
| DD_FAIL_QUIETLY_EACCES));
+ /* the source of the problem:
+ * - first we try to load component, as we use it on Fedora
+ */
+ char *source = dd_load_text_ext(dd, FILENAME_COMPONENT, 0
+ | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+ | DD_FAIL_QUIETLY_ENOENT
+ | DD_FAIL_QUIETLY_EACCES
+ );
+ /* if we don't have component, we fallback to executable */
+ if (!source)
+ {
+ source = dd_load_text_ext(dd, FILENAME_EXECUTABLE, 0
+ | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+ | DD_FAIL_QUIETLY_ENOENT
+ | DD_FAIL_QUIETLY_EACCES
+ );
+ }
+
+ g_variant_builder_add (builder, "{ss}", g_strdup("source"), source);
+ char *msg = dd_load_text_ext(dd, FILENAME_REPORTED_TO, 0
+ | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+ | DD_FAIL_QUIETLY_ENOENT
+ | DD_FAIL_QUIETLY_EACCES
+ );
+ if (msg)
+ g_variant_builder_add (builder, "{ss}",
g_strdup(FILENAME_REPORTED_TO), msg);
+
+ dd_close(dd);
+
+ GVariant *response = g_variant_new("(a{ss})", builder);
+ g_variant_builder_unref(builder);
according to me, you are leaking everywhere here. g_variant_builde_unref
only count donw reference counter and you should take care of all returned
vaules from load_text and g_strdup (and of course you should have to use
xstrdup or check g_strdup to NULL)
+ g_dbus_method_invocation_return_value(invocation, response);
+ }
+
+ else if (g_strcmp0(method_name, "Quit") == 0)
+ {
+ VERB1 log("Quit");
+
+ g_dbus_method_invocation_return_value(invocation, NULL);
+
+ g_main_loop_quit(loop);
+
+ }
+}
+
+/* for now */
+static const GDBusInterfaceVTable interface_vtable =
+{
+ handle_method_call,
+ NULL,
+ NULL,
+};
this looks like a function. I don't have any strong opinion here, but
more readable solution is
static const foo = {
.x = bar;
};
what is problem here is big or little endians. C doen't guarantee order
of list fields. you have to use
static const GDBusInterfaceVTable interface_vtable =
{
.GDBusInterfaceMethodCallFunc = handle_method_call,
.GDBusInterfaceGetPropertyFunc = NULL,
.GDBusInterfaceSetPropertyFunc = NULL,
};
- ok, changed to:
static const GDBusInterfaceVTable interface_vtable =
{
.method_call = handle_method_call,
.get_property = NULL,
.set_property = NULL,
};
+static void on_name_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+}
e? couldn't be set to NULL at g_bus_own_name call?
- ok
+static void on_name_lost (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ g_print(_("The name '%s' has been lost, please check if other "
+ "service owning the name is not running.\n"), name);
+ exit(1);
daemon should not exit(1)
- why not? it failed to initialize, so we should inform user about it...
+}
+
+int main (int argc, char *argv[])
+{
+ /* I18n */
+ setlocale(LC_ALL, "");
+#if ENABLE_NLS
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+#endif
+ guint owner_id;
+
+ abrt_init(argv);
+
+ const char *program_usage_string = _(
+ "& [options]"
+ );
+ enum {
+ OPT_v = 1<< 0,
+ OPT_t = 1<< 1,
+ };
+ /* Keep enum above and order of options below in sync! */
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_INTEGER('t', NULL,&s_timeout, _("Exit after NUM seconds of
inactivity")),
+ OPT_END()
+ };
+ unsigned opts = parse_opts(argc, argv, program_options,
program_usage_string);
+
+ export_abrt_envvars(0);
+
+ /* When dbus daemon starts us, it doesn't set PATH
+ * (I saw it set only DBUS_STARTER_ADDRESS and DBUS_STARTER_BUS_TYPE).
+ * In this case, set something sane:
+ */
+ const char *env_path = getenv("PATH");
+ if (!env_path || !env_path[0])
+ putenv((char*)"PATH=/usr/sbin:/usr/bin:/sbin:/bin");
+
+ msg_prefix = "abrt-dbus"; /* for log(), error_msg() and such */
+
+ if (!(opts& OPT_t))
+ s_timeout = 120; //if the timeout is not set we default to 120sec
s_timeout is not used; it's write only
- no, it's not:
55: g_timeout = g_timeout_add_seconds(s_timeout, on_timeout_cb, NULL);
+static PolkitResult do_check(PolkitSubject *subject, const char *action_id)
+{
...
...
...
+ if (polkit_authorization_result_get_is_challenge(auth_result))
+ {
+ /* Can't happen (happens only with
+ * POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE flag) */
+ result = PolkitChallenge;
+ goto out;
+ }
+
+ if (polkit_authorization_result_get_is_authorized(auth_result))
+ {
+ result = PolkitYes;
+ goto out;
pointless goto; you will reach the out after jump off the *if*
- well, it's a defensive coding, I doesn't break anything, but it could
if we add some code later and forget to add the goto.. so I propose to
leave it there
+ }
+
+out:
+ g_object_unref(auth_result);
+ return result;
+}
comment please, because I haven't run it yet