static gboolean add_interface(struct generic_data *data, const char *name, const GDBusMethodTable *methods, const GDBusSignalTable *signals, const GDBusPropertyTable *properties, void *user_data, GDBusDestroyFunction destroy) { struct interface_data *iface; const GDBusMethodTable *method; const GDBusSignalTable *signal; const GDBusPropertyTable *property; for (method = methods; method && method->name; method++) { if (!check_experimental(method->flags, G_DBUS_METHOD_FLAG_EXPERIMENTAL)) goto done; } for (signal = signals; signal && signal->name; signal++) { if (!check_experimental(signal->flags, G_DBUS_SIGNAL_FLAG_EXPERIMENTAL)) goto done; } for (property = properties; property && property->name; property++) { if (!check_experimental(property->flags, G_DBUS_PROPERTY_FLAG_EXPERIMENTAL)) goto done; } /* Nothing to register */ return FALSE; done: iface = g_new0(struct interface_data, 1); iface->name = g_strdup(name); iface->methods = methods; iface->signals = signals; iface->properties = properties; iface->user_data = user_data; iface->destroy = destroy; data->interfaces = g_slist_append(data->interfaces, iface); if (data->parent == NULL) return TRUE; data->added = g_slist_append(data->added, iface); if (data->process_id > 0) return TRUE; data->process_id = g_idle_add(process_changes, data); return TRUE; }
static void append_properties(struct interface_data *data, DBusMessageIter *iter) { DBusMessageIter dict; const GDBusPropertyTable *p; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); for (p = data->properties; p && p->name; p++) { if (check_experimental(p->flags, G_DBUS_PROPERTY_FLAG_EXPERIMENTAL)) continue; if (p->get == NULL) continue; if (p->exists != NULL && !p->exists(p, data->user_data)) continue; append_property(data, p, &dict); } dbus_message_iter_close_container(iter, &dict); }
static inline const GDBusPropertyTable *find_property(const GDBusPropertyTable *properties, const char *name) { const GDBusPropertyTable *p; for (p = properties; p && p->name; p++) { if (strcmp(name, p->name) != 0) continue; if (check_experimental(p->flags, G_DBUS_PROPERTY_FLAG_EXPERIMENTAL)) break; return p; } return NULL; }
static DBusHandlerResult generic_message(DBusConnection *connection, DBusMessage *message, void *user_data) { struct generic_data *data = user_data; struct interface_data *iface; const GDBusMethodTable *method; const char *interface; interface = dbus_message_get_interface(message); iface = find_interface(data->interfaces, interface); if (iface == NULL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; for (method = iface->methods; method && method->name && method->function; method++) { if (dbus_message_is_method_call(message, iface->name, method->name) == FALSE) continue; if (check_experimental(method->flags, G_DBUS_METHOD_FLAG_EXPERIMENTAL)) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; if (g_dbus_args_have_signature(method->in_args, message) == FALSE) continue; if (check_privilege(connection, message, method, iface->user_data) == TRUE) return DBUS_HANDLER_RESULT_HANDLED; return process_message(connection, message, method, iface->user_data); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
static void generate_interface_xml(GString *gstr, struct interface_data *iface) { const GDBusMethodTable *method; const GDBusSignalTable *signal; const GDBusPropertyTable *property; for (method = iface->methods; method && method->name; method++) { if (check_experimental(method->flags, G_DBUS_METHOD_FLAG_EXPERIMENTAL)) continue; g_string_append_printf(gstr, "<method name=\"%s\">", method->name); print_arguments(gstr, method->in_args, "in"); print_arguments(gstr, method->out_args, "out"); if (method->flags & G_DBUS_METHOD_FLAG_DEPRECATED) g_string_append_printf(gstr, G_DBUS_ANNOTATE_DEPRECATED); if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) g_string_append_printf(gstr, G_DBUS_ANNOTATE_NOREPLY); g_string_append_printf(gstr, "</method>"); } for (signal = iface->signals; signal && signal->name; signal++) { if (check_experimental(signal->flags, G_DBUS_SIGNAL_FLAG_EXPERIMENTAL)) continue; g_string_append_printf(gstr, "<signal name=\"%s\">", signal->name); print_arguments(gstr, signal->args, NULL); if (signal->flags & G_DBUS_SIGNAL_FLAG_DEPRECATED) g_string_append_printf(gstr, G_DBUS_ANNOTATE_DEPRECATED); g_string_append_printf(gstr, "</signal>\n"); } for (property = iface->properties; property && property->name; property++) { if (check_experimental(property->flags, G_DBUS_PROPERTY_FLAG_EXPERIMENTAL)) continue; g_string_append_printf(gstr, "<property name=\"%s\"" " type=\"%s\" access=\"%s%s\">", property->name, property->type, property->get ? "read" : "", property->set ? "write" : ""); if (property->flags & G_DBUS_PROPERTY_FLAG_DEPRECATED) g_string_append_printf(gstr, G_DBUS_ANNOTATE_DEPRECATED); g_string_append_printf(gstr, "</property>"); } }
int main(int argc, const char *argv[]) { const char *repos_path; apr_pool_t *pool; svn_boolean_t prop = FALSE, data = FALSE; svn_boolean_t quiet = FALSE; svn_error_t *err; apr_getopt_t *os; const apr_getopt_option_t options[] = { {"data", OPT_DATA, 0, N_("display data reps stats")}, {"prop", OPT_PROP, 0, N_("display prop reps stats")}, {"both", OPT_BOTH, 0, N_("display combined (data+prop) reps stats")}, {"quiet", 'q', 0, N_("no progress (only errors) to stderr")}, {"help", 'h', 0, N_("display this help")}, {"version", OPT_VERSION, 0, N_("show program version information")}, {0, 0, 0, 0} }; /* Initialize the app. */ if (svn_cmdline_init("svn-rep-sharing-stats", stderr) != EXIT_SUCCESS) return EXIT_FAILURE; /* Create our top-level pool. Use a separate mutexless allocator, * given this application is single threaded. */ pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE)); /* Check library versions */ err = check_lib_versions(); if (err) return svn_cmdline_handle_exit_error(err, pool, "svn-rep-sharing-stats: "); err = svn_cmdline__getopt_init(&os, argc, argv, pool); if (err) return svn_cmdline_handle_exit_error(err, pool, "svn-rep-sharing-stats: "); SVN_INT_ERR(check_experimental()); os->interleave = 1; while (1) { int opt; const char *arg; apr_status_t status = apr_getopt_long(os, options, &opt, &arg); if (APR_STATUS_IS_EOF(status)) break; if (status != APR_SUCCESS) { usage(pool); return EXIT_FAILURE; } switch (opt) { case OPT_DATA: data = TRUE; break; /* It seems we don't actually rep-share props yet. */ case OPT_PROP: prop = TRUE; break; case OPT_BOTH: data = TRUE; prop = TRUE; break; case 'q': quiet = TRUE; break; case 'h': help(options, pool); break; case OPT_VERSION: SVN_INT_ERR(version(pool)); exit(0); break; default: usage(pool); return EXIT_FAILURE; } } /* Exactly 1 non-option argument, * and at least one of "--data"/"--prop"/"--both". */ if (os->ind + 1 != argc || (!data && !prop)) { usage(pool); return EXIT_FAILURE; } /* Grab REPOS_PATH from argv. */ SVN_INT_ERR(svn_utf_cstring_to_utf8(&repos_path, os->argv[os->ind], pool)); repos_path = svn_dirent_internal_style(repos_path, pool); set_up_cancellation(); /* Do something. */ SVN_INT_ERR(process(repos_path, prop, data, quiet, pool)); /* We're done. */ svn_pool_destroy(pool); /* Flush stdout to make sure that the user will see any printing errors. */ SVN_INT_ERR(svn_cmdline_fflush(stdout)); return EXIT_SUCCESS; }