/** * g_cancellable_connect: * @cancellable: A #GCancellable. * @callback: The #GCallback to connect. * @data: Data to pass to @callback. * @data_destroy_func: Free function for @data or %NULL. * * Convenience function to connect to the #GCancellable::cancelled * signal. Also handles the race condition that may happen * if the cancellable is cancelled right before connecting. * * @callback is called at most once, either directly at the * time of the connect if @cancellable is already cancelled, * or when @cancellable is cancelled in some thread. * * @data_destroy_func will be called when the handler is * disconnected, or immediately if the cancellable is already * cancelled. * * See #GCancellable::cancelled for details on how to use this. * * Returns: The id of the signal handler or 0 if @cancellable has already * been cancelled. * * Since: 2.22 */ gulong g_cancellable_connect (GCancellable *cancellable, GCallback callback, gpointer data, GDestroyNotify data_destroy_func) { gulong id; g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), 0); G_LOCK (cancellable); if (cancellable->priv->cancelled) { void (*_callback) (GCancellable *cancellable, gpointer user_data); _callback = (void *)callback; id = 0; _callback (cancellable, data); if (data_destroy_func) data_destroy_func (data); } else { id = g_signal_connect_data (cancellable, "cancelled", callback, data, (GClosureNotify) data_destroy_func, 0); } G_UNLOCK (cancellable); return id; }
void g_slist_free (GSList *list) { if (list) { GSList *last_node = list; #ifdef ENABLE_GC_FRIENDLY while (last_node->next) { last_node->data = NULL; last_node = last_node->next; } last_node->data = NULL; #else /* !ENABLE_GC_FRIENDLY */ list->data = list->next; #endif /* ENABLE_GC_FRIENDLY */ G_LOCK (current_allocator); last_node->next = current_allocator->free_lists; current_allocator->free_lists = list; G_UNLOCK (current_allocator); } }
static void g_hash_node_destroy (GHashNode *hash_node, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func) { if (key_destroy_func) key_destroy_func (hash_node->key); if (value_destroy_func) value_destroy_func (hash_node->value); #ifdef ENABLE_GC_FRIENDLY hash_node->key = NULL; hash_node->value = NULL; #endif /* ENABLE_GC_FRIENDLY */ #ifdef DISABLE_MEM_POOLS g_free (hash_node); #else G_LOCK (g_hash_global); hash_node->next = node_free_list; node_free_list = hash_node; G_UNLOCK (g_hash_global); #endif }
BALDE_API void balde_app_add_url_rule(balde_app_t *app, const gchar *endpoint, const gchar *rule, const balde_http_method_t method, balde_view_func_t view_func) { BALDE_APP_READ_ONLY(app); GError *tmp_error = NULL; balde_view_t *view = g_new(balde_view_t, 1); view->url_rule = g_new(balde_url_rule_t, 1); view->url_rule->endpoint = endpoint; view->url_rule->rule = rule; view->url_rule->match = balde_parse_url_rule(view->url_rule->rule, &tmp_error); if (tmp_error != NULL) { g_propagate_error(&(app->error), tmp_error); balde_app_free_views(view); return; } view->url_rule->method = method | BALDE_HTTP_OPTIONS; if (view->url_rule->method & BALDE_HTTP_GET) view->url_rule->method |= BALDE_HTTP_HEAD; view->view_func = view_func; G_LOCK(views); app->priv->views = g_slist_append(app->priv->views, view); G_UNLOCK(views); }
/** * g_io_scheduler_cancel_all_jobs: * * Cancels all cancellable I/O jobs. * * A job is cancellable if a #GCancellable was passed into * g_io_scheduler_push_job(). **/ void g_io_scheduler_cancel_all_jobs (void) { GSList *cancellable_list, *l; G_LOCK (active_jobs); cancellable_list = NULL; for (l = active_jobs; l != NULL; l = l->next) { GIOSchedulerJob *job = l->data; if (job->cancellable) cancellable_list = g_slist_prepend (cancellable_list, g_object_ref (job->cancellable)); } G_UNLOCK (active_jobs); for (l = cancellable_list; l != NULL; l = l->next) { GCancellable *c = l->data; g_cancellable_cancel (c); g_object_unref (c); } g_slist_free (cancellable_list); }
static void g_hash_node_destroy (MonoGHashNode *hash_node, MonoGHashGCType type, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func) { if (key_destroy_func) key_destroy_func (hash_node->key); if (value_destroy_func) value_destroy_func (hash_node->value); hash_node->key = NULL; hash_node->value = NULL; G_LOCK (g_hash_global); #if defined(HAVE_SGEN_GC) || defined(HAVE_BOEHM_GC) hash_node->next = node_free_lists [type]; node_free_lists [type] = hash_node; #else hash_node->next = node_free_list; node_free_list = hash_node; #endif G_UNLOCK (g_hash_global); }
/** * g_io_scheduler_push_job: * @job_func: a #GIOSchedulerJobFunc. * @user_data: data to pass to @job_func * @notify: (allow-none): a #GDestroyNotify for @user_data, or %NULL * @io_priority: the [I/O priority][io-priority] * of the request. * @cancellable: optional #GCancellable object, %NULL to ignore. * * Schedules the I/O job to run in another thread. * * @notify will be called on @user_data after @job_func has returned, * regardless whether the job was cancelled or has run to completion. * * If @cancellable is not %NULL, it can be used to cancel the I/O job * by calling g_cancellable_cancel() or by calling * g_io_scheduler_cancel_all_jobs(). * * Deprecated: use #GThreadPool or g_task_run_in_thread() **/ void g_io_scheduler_push_job (GIOSchedulerJobFunc job_func, gpointer user_data, GDestroyNotify notify, gint io_priority, GCancellable *cancellable) { GIOSchedulerJob *job; GTask *task; g_return_if_fail (job_func != NULL); job = g_slice_new0 (GIOSchedulerJob); job->job_func = job_func; job->data = user_data; job->destroy_notify = notify; if (cancellable) job->cancellable = g_object_ref (cancellable); job->context = g_main_context_ref_thread_default (); G_LOCK (active_jobs); active_jobs = g_list_prepend (active_jobs, job); job->active_link = active_jobs; G_UNLOCK (active_jobs); task = g_task_new (NULL, cancellable, NULL, NULL); G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_task_set_source_tag (task, g_io_scheduler_push_job); G_GNUC_END_IGNORE_DEPRECATIONS g_task_set_task_data (task, job, (GDestroyNotify)g_io_job_free); g_task_set_priority (task, io_priority); g_task_run_in_thread (task, io_job_thread); g_object_unref (task); }
static gboolean gst_object_set_name_default (GstObject * object) { const gchar *type_name; gint count; gchar *name, *tmp; gboolean result; GQuark q; /* to ensure guaranteed uniqueness across threads, only one thread * may ever assign a name */ G_LOCK (object_name_mutex); if (!object_name_counts) { g_datalist_init (&object_name_counts); } q = g_type_qname (G_OBJECT_TYPE (object)); count = GPOINTER_TO_INT (g_datalist_id_get_data (&object_name_counts, q)); g_datalist_id_set_data (&object_name_counts, q, GINT_TO_POINTER (count + 1)); G_UNLOCK (object_name_mutex); /* GstFooSink -> foosinkN */ type_name = g_quark_to_string (q); if (strncmp (type_name, "Gst", 3) == 0) type_name += 3; tmp = g_strdup_printf ("%s%d", type_name, count); name = g_ascii_strdown (tmp, -1); g_free (tmp); result = gst_object_set_name (object, name); g_free (name); return result; }
static void context_rule_removed (ERuleContext *ctx, EFilterRule *rule) { gpointer key, folder = NULL; d(printf("rule removed; %s\n", rule->name)); /* TODO: remove from folder info cache? */ G_LOCK (vfolder); if (g_hash_table_lookup_extended (vfolder_hash, rule->name, &key, &folder)) { g_hash_table_remove (vfolder_hash, key); g_free (key); } G_UNLOCK (vfolder); /* FIXME Not passing a GCancellable or GError. */ camel_store_delete_folder_sync ( vfolder_store, rule->name, NULL, NULL); /* this must be unref'd after its deleted */ if (folder) g_object_unref ((CamelFolder *) folder); }
static void sendrecv_answerer_fakesink_hand_off (GstElement * fakesink, GstBuffer * buf, GstPad * pad, gpointer data) { HandOffData *hod = (HandOffData *) data; GstElement *pipeline; check_caps (pad, hod); pipeline = GST_ELEMENT (gst_element_get_parent (fakesink)); G_LOCK (check_receive_lock); if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pipeline), OFFERER_RECEIVES_AUDIO))) { g_object_set (G_OBJECT (fakesink), "signal-handoffs", FALSE, NULL); g_idle_add (quit_main_loop_idle, hod->loop); } else { g_object_set_data (G_OBJECT (pipeline), ANSWERER_RECEIVES_AUDIO, GINT_TO_POINTER (TRUE)); } G_UNLOCK (check_receive_lock); g_object_unref (pipeline); }
/** * g_datalist_remove_data: * @dl: a datalist. * @k: the string identifying the data element. * * Removes an element using its string identifier. The data element's * destroy function is called if it has been set. **/ void g_datalist_id_set_data_full (GData **datalist, GQuark key_id, gpointer data, GDestroyNotify destroy_func) { g_return_if_fail (datalist != NULL); if (!data) g_return_if_fail (destroy_func == NULL); if (!key_id) { if (data) g_return_if_fail (key_id > 0); else return; } G_LOCK (g_dataset_global); if (!g_dataset_location_ht) g_data_initialize (); g_data_set_internal (datalist, key_id, data, destroy_func, NULL); G_UNLOCK (g_dataset_global); }
/** * fen_init: * * FEN subsystem initializing. */ gboolean fen_init () { static gboolean initialized = FALSE; static gboolean result = FALSE; G_LOCK (fen_lock); if (initialized) { G_UNLOCK (fen_lock); return result; } result = node_class_init(); if (!result) { G_UNLOCK (fen_lock); return result; } initialized = TRUE; G_UNLOCK (fen_lock); return result; }
static void remove_client (Client * client) { g_print ("Removing connection %s\n", client->name); g_free (client->name); if (client->isource) { g_source_destroy (client->isource); g_source_unref (client->isource); } if (client->tosource) { g_source_destroy (client->tosource); g_source_unref (client->tosource); } g_object_unref (client->connection); g_byte_array_unref (client->current_message); G_LOCK (clients); clients = g_list_remove (clients, client); G_UNLOCK (clients); g_slice_free (Client, client); }
/** * pka_manager_find_plugin: * @context: A #PkaContext. * @plugin_id: The plugin identifier. * @plugin: A location for a #PkaPlugin. * @error: A location for a #GError, or %NULL. * * Finds the plugin matching the requested @plugin_id. If the context * does not have permissions, this operation will fail. * * If successful, the plugin instance is stored in @plugin. The caller * owns a reference to this plugin and should free it with g_object_unref(). * * Returns: %TRUE if successful; otherwise %FALSE. * Side effects: None. */ gboolean pka_manager_find_plugin (PkaContext *context, /* IN */ const gchar *plugin_id, /* IN */ PkaPlugin **plugin, /* OUT */ GError **error) /* OUT */ { PkaPlugin *iter; gint i; g_return_val_if_fail(context != NULL, FALSE); g_return_val_if_fail(plugin != NULL, FALSE); ENTRY; *plugin = NULL; if (!plugin_id) { GOTO(failed); } G_LOCK(plugins); for (i = 0; i < manager.plugins->len; i++) { iter = g_ptr_array_index(manager.plugins, i); if (g_str_equal(pka_plugin_get_id(iter), plugin_id)) { /* * TODO: Verify permissions. */ *plugin = g_object_ref(iter); BREAK; } } G_UNLOCK(plugins); failed: if (!*plugin) { g_set_error(error, PKA_PLUGIN_ERROR, PKA_PLUGIN_ERROR_INVALID_TYPE, "The specified plugin could not be found."); } RETURN(*plugin != NULL); }
static void pad_added_cb (GstElement * element, GstPad * pad, gpointer data) { GstElement *pipeline = GST_ELEMENT (data); GstElement *wavenc, *sink; GstPadLinkReturn ret; GstPad *sinkpad; gchar *msg; if (gst_pad_get_direction (pad) != GST_PAD_SRC) return; wavenc = gst_element_factory_make ("wavenc", NULL); #ifdef MANUAL_CHECK { gchar *filename; G_LOCK (mutex); filename = g_strdup_printf ("file_%u.wv", id++); GST_DEBUG ("Creating file %s", filename); G_UNLOCK (mutex); sink = gst_element_factory_make ("filesink", NULL); g_object_set (G_OBJECT (sink), "location", filename, NULL); g_free (filename); } #else { sink = gst_element_factory_make ("fakesink", NULL); } #endif g_object_set (G_OBJECT (sink), "sync", FALSE, "async", FALSE, NULL); gst_bin_add_many (GST_BIN (pipeline), wavenc, sink, NULL); sinkpad = gst_element_get_static_pad (wavenc, "sink"); if ((ret = gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) { msg = g_strdup_printf ("Can not link pads (%d)", ret); gst_object_unref (sinkpad); goto failed; } gst_object_unref (sinkpad); if (!gst_element_link (wavenc, sink)) { msg = g_strdup_printf ("Can not link elements"); goto failed; } sinkpad = gst_element_get_static_pad (sink, "sink"); gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, buffer_probe_cb, NULL, NULL); gst_object_unref (sinkpad); gst_element_sync_state_with_parent (wavenc); gst_element_sync_state_with_parent (sink); G_LOCK (hash_mutex); g_hash_table_insert (hash, GST_OBJECT_NAME (pad), wavenc); G_UNLOCK (hash_mutex); return; failed: gst_element_set_state (wavenc, GST_STATE_NULL); gst_element_set_state (sink, GST_STATE_NULL); gst_bin_remove_many (GST_BIN (pipeline), wavenc, sink, NULL); GST_ERROR ("Error %s", msg); fail (msg); g_free (msg); g_idle_add ((GSourceFunc) quit_main_loop, NULL); }
/** * g_dbus_error_encode_gerror: * @error: A #GError. * * Creates a D-Bus error name to use for @error. If @error matches * a registered error (cf. g_dbus_error_register_error()), the corresponding * D-Bus error name will be returned. * * Otherwise the a name of the form * `org.gtk.GDBus.UnmappedGError.Quark._ESCAPED_QUARK_NAME.Code_ERROR_CODE` * will be used. This allows other GDBus applications to map the error * on the wire back to a #GError using g_dbus_error_new_for_dbus_error(). * * This function is typically only used in object mappings to put a * #GError on the wire. Regular applications should not use it. * * Returns: A D-Bus error name (never %NULL). Free with g_free(). * * Since: 2.26 */ gchar * g_dbus_error_encode_gerror (const GError *error) { RegisteredError *re; gchar *error_name; g_return_val_if_fail (error != NULL, NULL); /* Ensure that e.g. G_DBUS_ERROR is registered using g_dbus_error_register_error() */ _g_dbus_initialize (); error_name = NULL; G_LOCK (error_lock); re = NULL; if (quark_code_pair_to_re != NULL) { QuarkCodePair pair; pair.error_domain = error->domain; pair.error_code = error->code; g_assert (dbus_error_name_to_re != NULL); /* check invariant */ re = g_hash_table_lookup (quark_code_pair_to_re, &pair); } if (re != NULL) { error_name = g_strdup (re->dbus_error_name); G_UNLOCK (error_lock); } else { const gchar *domain_as_string; GString *s; guint n; G_UNLOCK (error_lock); /* We can't make a lot of assumptions about what domain_as_string * looks like and D-Bus is extremely picky about error names so * hex-encode it for transport across the wire. */ domain_as_string = g_quark_to_string (error->domain); /* 0 is not a domain; neither are non-quark integers */ g_return_val_if_fail (domain_as_string != NULL, NULL); s = g_string_new ("org.gtk.GDBus.UnmappedGError.Quark._"); for (n = 0; domain_as_string[n] != 0; n++) { gint c = domain_as_string[n]; if (g_ascii_isalnum (c)) { g_string_append_c (s, c); } else { guint nibble_top; guint nibble_bottom; g_string_append_c (s, '_'); nibble_top = ((int) domain_as_string[n]) >> 4; nibble_bottom = ((int) domain_as_string[n]) & 0x0f; if (nibble_top < 10) nibble_top += '0'; else nibble_top += 'a' - 10; if (nibble_bottom < 10) nibble_bottom += '0'; else nibble_bottom += 'a' - 10; g_string_append_c (s, nibble_top); g_string_append_c (s, nibble_bottom); } } g_string_append_printf (s, ".Code%d", error->code); error_name = g_string_free (s, FALSE); } return error_name; }
/* HOLDS: g_dataset_global_lock */ static inline gpointer g_data_set_internal (GData **datalist, GQuark key_id, gpointer data, GDestroyNotify destroy_func, GDataset *dataset) { register GData *list; list = G_DATALIST_GET_POINTER (datalist); if (!data) { register GData *prev; prev = NULL; while (list) { if (list->id == key_id) { gpointer ret_data = NULL; if (prev) prev->next = list->next; else { G_DATALIST_SET_POINTER (datalist, list->next); /* the dataset destruction *must* be done * prior to invocation of the data destroy function */ if (!list->next && dataset) g_dataset_destroy_internal (dataset); } /* the GData struct *must* already be unlinked * when invoking the destroy function. * we use (data==NULL && destroy_func!=NULL) as * a special hint combination to "steal" * data without destroy notification */ if (list->destroy_func && !destroy_func) { G_UNLOCK (g_dataset_global); list->destroy_func (list->data); G_LOCK (g_dataset_global); } else ret_data = list->data; g_slice_free (GData, list); return ret_data; } prev = list; list = list->next; } } else { while (list) { if (list->id == key_id) { if (!list->destroy_func) { list->data = data; list->destroy_func = destroy_func; } else { register GDestroyNotify dfunc; register gpointer ddata; dfunc = list->destroy_func; ddata = list->data; list->data = data; list->destroy_func = destroy_func; /* we need to have updated all structures prior to * invocation of the destroy function */ G_UNLOCK (g_dataset_global); dfunc (ddata); G_LOCK (g_dataset_global); } return NULL; } list = list->next; } list = g_slice_new (GData); list->next = G_DATALIST_GET_POINTER (datalist); list->id = key_id; list->data = data; list->destroy_func = destroy_func; G_DATALIST_SET_POINTER (datalist, list); } return NULL; }
/** * mate_vfs_resolve: * @hostname: hostname you want to resolve. * @handle: pointer to a pointer to a #MateVFSResolveHandle. * * Tries to resolve @hostname. If the operation was successful you can * get the resolved addresses in form of #MateVFSAddress by calling * mate_vfs_resolve_next_address(). * * Return value: A #MateVFSResult indicating the success of the operation. * * Since: 2.8 */ MateVFSResult mate_vfs_resolve (const char *hostname, MateVFSResolveHandle **handle) { #ifdef HAVE_GETADDRINFO struct addrinfo hints, *result; int res; gboolean retry = TRUE; restart: memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_STREAM; #ifdef ENABLE_IPV6 # ifdef HAVE_AI_ADDRCONFIG /* RFC3493 */ hints.ai_flags = AI_ADDRCONFIG; hints.ai_family = AF_UNSPEC; # else hints.ai_family = AF_UNSPEC; # endif #else hints.ai_family = AF_INET; #endif /* ENABLE_IPV6 */ res = getaddrinfo (hostname, NULL, &hints, &result); if (res != 0) { if (retry && restart_resolve ()) { retry = FALSE; goto restart; } else { return _mate_vfs_result_from_gai_error (res); } } *handle = g_new0 (MateVFSResolveHandle, 1); (*handle)->result = result; (*handle)->current = result; return MATE_VFS_OK; #else /* HAVE_GETADDRINFO */ struct hostent resbuf, *result = &resbuf; MateVFSResult ret; int res; gboolean retry = TRUE; #ifdef HAVE_GETHOSTBYNAME_R_GLIBC size_t buflen; char *buf; int h_errnop; restart: buf = NULL; buflen = INIT_BUFSIZE; h_errnop = 0; do { buf = g_renew (char, buf, buflen); res = gethostbyname_r (hostname, &resbuf, buf, buflen, &result, &h_errnop); buflen *= 2; } while (res == ERANGE); if (res != 0 || result == NULL || result->h_addr_list[0] == NULL) { g_free (buf); if (retry && restart_resolve ()) { retry = FALSE; goto restart; } else { return mate_vfs_result_from_h_errno_val (h_errnop); } } ret = resolvehandle_from_hostent (result, handle); g_free (buf); #elif HAVE_GETHOSTBYNAME_R_SOLARIS size_t buflen; char *buf; int h_errnop; restart: buf = NULL; buflen = INIT_BUFSIZE; h_errnop = 0; do { buf = g_renew (char, buf, buflen); result = gethostbyname_r (hostname, &resbuf, buf, buflen, &h_errnop); buflen *= 2; } while (h_errnop == ERANGE); if (result == NULL) { g_free (buf); if (retry && restart_resolve ()) { retry = FALSE; goto restart; } else { return mate_vfs_result_from_h_errno_val (h_errnop); } } ret = resolvehandle_from_hostent (result, handle); g_free (buf); #elif HAVE_GETHOSTBYNAME_R_HPUX struct hostent_data buf; restart: res = gethostbyname_r (hostname, result, &buf); if (res != 0) { if (retry && restart_resolve ()) { retry = FALSE; goto restart; } else { return mate_vfs_result_from_h_errno_val (h_errnop); } } ret = resolvehandle_from_hostent (result, handle); #else /* !HAVE_GETHOSTBYNAME_R_GLIBC && !HAVE_GETHOSTBYNAME_R_SOLARIS && !HAVE_GETHOSTBYNAME_R_HPUX */ res = 0;/* only set to avoid unused variable error */ G_LOCK (dns_lock); restart: result = gethostbyname (hostname); if (result == NULL) { if (retry && restart_resolve ()) { retry = FALSE; goto restart; } else { #ifndef G_OS_WIN32 ret = mate_vfs_result_from_h_errno (); #else switch (WSAGetLastError ()) { case WSAHOST_NOT_FOUND: ret = MATE_VFS_ERROR_HOST_NOT_FOUND; break; case WSANO_DATA: ret = MATE_VFS_ERROR_HOST_HAS_NO_ADDRESS; break; case WSATRY_AGAIN: case WSANO_RECOVERY: ret = MATE_VFS_ERROR_NAMESERVER; default: ret = MATE_VFS_ERROR_GENERIC; } #endif } } else { ret = resolvehandle_from_hostent (result, handle); } G_UNLOCK (dns_lock); #endif /* !HAVE_GETHOSTBYNAME_R_GLIBC && !HAVE_GETHOSTBYNAME_R_SOLARIS && !HAVE_GETHOSTBYNAME_R_HPUX */ return ret; #endif /* HAVE_GETADDRINFO */ }
void resolve_sockaddr(gchar *result, gsize *result_len, GSockAddr *saddr, gboolean usedns, gboolean usefqdn, gboolean use_dns_cache, gboolean normalize_hostnames) { gchar *hname; gboolean positive; gchar *p, buf[256]; if (saddr && saddr->sa.sa_family != AF_UNIX) { if (saddr->sa.sa_family == AF_INET #if ENABLE_IPV6 || saddr->sa.sa_family == AF_INET6 #endif ) { void *addr; socklen_t addr_len G_GNUC_UNUSED; if (saddr->sa.sa_family == AF_INET) { addr = &((struct sockaddr_in *) &saddr->sa)->sin_addr; addr_len = sizeof(struct in_addr); } #if ENABLE_IPV6 else { addr = &((struct sockaddr_in6 *) &saddr->sa)->sin6_addr; addr_len = sizeof(struct in6_addr); } #endif hname = NULL; if (usedns) { if ((!use_dns_cache || !dns_cache_lookup(saddr->sa.sa_family, addr, (const gchar **) &hname, &positive)) && usedns != 2) { #ifdef HAVE_GETNAMEINFO if (getnameinfo(&saddr->sa, saddr->salen, buf, sizeof(buf), NULL, 0, 0) == 0) hname = buf; #else struct hostent *hp; G_LOCK(resolv_lock); hp = gethostbyaddr(addr, addr_len, saddr->sa.sa_family); G_UNLOCK(resolv_lock); hname = (hp && hp->h_name) ? hp->h_name : NULL; #endif if (hname) positive = TRUE; if (use_dns_cache && hname) { /* resolution success, store this as a positive match in the cache */ dns_cache_store(FALSE, saddr->sa.sa_family, addr, hname, TRUE); } } } if (!hname) { inet_ntop(saddr->sa.sa_family, addr, buf, sizeof(buf)); hname = buf; if (use_dns_cache) dns_cache_store(FALSE, saddr->sa.sa_family, addr, hname, FALSE); } else { if (!usefqdn && positive) { /* we only truncate hostnames if they were positive * matches (e.g. real hostnames and not IP * addresses) */ p = strchr(hname, '.'); if (p) { if (p - hname > sizeof(buf)) p = &hname[sizeof(buf)] - 1; memcpy(buf, hname, p - hname); buf[p - hname] = 0; hname = buf; } } } } else { g_assert_not_reached(); } } else { if (!local_hostname_fqdn[0]) reset_cached_hostname(); if (usefqdn) { /* avoid copy */ hname = local_hostname_fqdn; } else { hname = local_hostname_short; } } if (normalize_hostnames) { gint i; for (i = 0; hname[i] && i < ((*result_len) - 1); i++) { result[i] = g_ascii_tolower(hname[i]); } result[i] = '\0'; /* the closing \0 is not copied by the previous loop */ *result_len = i; } else { gsize len = strlen(hname); if (*result_len < len - 1) len = *result_len - 1; memcpy(result, hname, len); result[len] = 0; *result_len = len; } }
gboolean resolve_hostname(GSockAddr **addr, gchar *name) { if (addr) { #if HAVE_GETADDRINFO struct addrinfo hints; struct addrinfo *res; memset(&hints, 0, sizeof(hints)); hints.ai_family = (*addr)->sa.sa_family; hints.ai_socktype = 0; hints.ai_protocol = 0; if (getaddrinfo(name, NULL, &hints, &res) == 0) { /* we only use the first entry in the returned list */ switch ((*addr)->sa.sa_family) { case AF_INET: g_sockaddr_inet_set_address((*addr), ((struct sockaddr_in *) res->ai_addr)->sin_addr); break; #if ENABLE_IPV6 case AF_INET6: { guint16 port; /* we need to copy the whole sockaddr_in6 structure as it * might contain scope and other required data */ port = g_sockaddr_inet6_get_port(*addr); *g_sockaddr_inet6_get_sa(*addr) = *((struct sockaddr_in6 *) res->ai_addr); /* we need to restore the port number as it is zeroed out by the previous assignment */ g_sockaddr_inet6_set_port(*addr, port); break; } #endif default: g_assert_not_reached(); break; } freeaddrinfo(res); } else { msg_error("Error resolving hostname", evt_tag_str("host", name), NULL); return FALSE; } #else struct hostent *he; G_LOCK(resolv_lock); he = gethostbyname(name); if (he) { switch ((*addr)->sa.sa_family) { case AF_INET: g_sockaddr_inet_set_address((*addr), *(struct in_addr *) he->h_addr); break; default: g_assert_not_reached(); break; } G_UNLOCK(resolv_lock); } else { G_UNLOCK(resolv_lock); msg_error("Error resolving hostname", evt_tag_str("host", name), NULL); return FALSE; } #endif } return TRUE; }
static int camel_gethostbyaddr_r (const char *addr, int addrlen, int type, struct hostent *host, char *buf, size_t buflen, int *herr) { #ifdef ENABLE_IPv6 int retval, len; if ((retval = getnameinfo (addr, addrlen, buf, buflen, NULL, 0, NI_NAMEREQD)) != 0) { *herr = ai_to_herr (retval); return -1; } len = ALIGN (strlen (buf) + 1); if (buflen < IPv6_BUFLEN_MIN + len + addrlen + sizeof (char *)) return ERANGE; /* h_name */ host->h_name = buf; buf += len; /* h_aliases */ ((char **) buf)[0] = NULL; host->h_aliases = (char **) buf; buf += sizeof (char *); /* h_addrtype and h_length */ host->h_length = addrlen; host->h_addrtype = type; memcpy (buf, addr, host->h_length); addr = buf; buf += ALIGN (host->h_length); /* h_addr_list */ ((char **) buf)[0] = addr; ((char **) buf)[1] = NULL; host->h_addr_list = (char **) buf; return 0; #else /* No support for IPv6 addresses */ #ifdef HAVE_GETHOSTBYADDR_R #ifdef GETHOSTBYADDR_R_SEVEN_ARGS if (gethostbyaddr_r (addr, addrlen, type, host, buf, buflen, herr)) return 0; else return errno; #else struct hostent *hp; int retval; retval = gethostbyaddr_r (addr, addrlen, type, host, buf, buflen, &hp, herr); if (hp != NULL) { *herr = 0; retval = 0; } else if (retval == 0) { /* glibc 2.3.2 workaround - it seems that * gethostbyaddr_r will sometimes return 0 on fail and * fill @host with garbage strings from /etc/hosts * (failure to parse the file? who knows). Luckily, it * seems that we can rely on @hp being NULL on * fail. */ retval = -1; } return retval; #endif #else /* No support for gethostbyaddr_r */ struct hostent *h; G_LOCK (gethost_mutex); h = gethostbyaddr (addr, addrlen, type); if (!h) { *herr = h_errno; G_UNLOCK (gethost_mutex); return -1; } GETHOST_PROCESS (h, host, buf, buflen, herr); G_UNLOCK (gethost_mutex); return 0; #endif /* HAVE_GETHOSTBYADDR_R */ #endif /* ENABLE_IPv6 */ }
static int camel_gethostbyname_r (const char *name, struct hostent *host, char *buf, size_t buflen, int *herr) { #ifdef ENABLE_IPv6 struct addrinfo hints, *res; int retval, len; char *addr; memset (&hints, 0, sizeof (struct addrinfo)); #ifdef HAVE_AI_ADDRCONFIG hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; #else hints.ai_flags = AI_CANONNAME; #endif hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if ((retval = getaddrinfo (name, NULL, &hints, &res)) != 0) { *herr = ai_to_herr (retval); return -1; } len = ALIGN (strlen (res->ai_canonname) + 1); if (buflen < IPv6_BUFLEN_MIN + len + res->ai_addrlen + sizeof (char *)) return ERANGE; /* h_name */ strcpy (buf, res->ai_canonname); host->h_name = buf; buf += len; /* h_aliases */ ((char **) buf)[0] = NULL; host->h_aliases = (char **) buf; buf += sizeof (char *); /* h_addrtype and h_length */ host->h_length = res->ai_addrlen; if (res->ai_family == PF_INET6) { host->h_addrtype = AF_INET6; addr = (char *) &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; } else { host->h_addrtype = AF_INET; addr = (char *) &((struct sockaddr_in *) res->ai_addr)->sin_addr; } memcpy (buf, addr, host->h_length); addr = buf; buf += ALIGN (host->h_length); /* h_addr_list */ ((char **) buf)[0] = addr; ((char **) buf)[1] = NULL; host->h_addr_list = (char **) buf; freeaddrinfo (res); return 0; #else /* No support for IPv6 addresses */ #ifdef HAVE_GETHOSTBYNAME_R #ifdef GETHOSTBYNAME_R_FIVE_ARGS if (gethostbyname_r (name, host, buf, buflen, herr)) return 0; else return errno; #else struct hostent *hp; int retval; retval = gethostbyname_r (name, host, buf, buflen, &hp, herr); if (hp != NULL) { *herr = 0; } else if (retval == 0) { /* glibc 2.3.2 workaround - it seems that * gethostbyname_r will sometimes return 0 on fail and * not set the hostent values (hence the crash in bug * #56337). Hopefully we can depend on @hp being NULL * in this error case like we do with * gethostbyaddr_r(). */ retval = -1; } return retval; #endif #else /* No support for gethostbyname_r */ struct hostent *h; G_LOCK (gethost_mutex); h = gethostbyname (name); if (!h) { *herr = h_errno; G_UNLOCK (gethost_mutex); return -1; } GETHOST_PROCESS (h, host, buf, buflen, herr); G_UNLOCK (gethost_mutex); return 0; #endif /* HAVE_GETHOSTBYNAME_R */ #endif /* ENABLE_IPv6 */ }
void select_sound(GtkWidget *menu_item, gpointer data) { GtkWidget *dialog; GtkFileFilter *filter, *filter_all; play = FALSE; dialog = gtk_file_chooser_dialog_new(_("Choose a file"), NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, "Stop Sound", 1000, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(filter, "*.[mM][pP][1-3]"); gtk_file_filter_add_pattern(filter, "*.[wW][aA][vV]"); gtk_file_filter_add_pattern(filter, "*.[oO][gG][gG]"); gtk_file_filter_set_name(filter, _("Sound Files")); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); filter_all = gtk_file_filter_new(); gtk_file_filter_add_pattern(filter_all, "*"); gtk_file_filter_set_name(filter_all, _("All Files")); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter_all); gchar *dir = g_build_filename(installation_dir, "etc", NULL); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); g_free(dir); gint r = gtk_dialog_run(GTK_DIALOG(dialog)); if (play) { // can start during dialog gtk_widget_destroy(dialog); return; } if (r == 1000) { // stop sound G_LOCK(sound); g_free(sound_file); sound_file = NULL; if (dev) ao_close(dev); dev = NULL; g_key_file_set_string(keyfile, "preferences", "soundfile", ""); gtk_widget_destroy(dialog); G_UNLOCK(sound); return; } if (r != GTK_RESPONSE_ACCEPT) { gtk_widget_destroy(dialog); return; } G_LOCK(sound); g_free(sound_file); sound_file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); g_key_file_set_string(keyfile, "preferences", "soundfile", sound_file); init_dev(); G_UNLOCK(sound); gtk_widget_destroy(dialog); }
/** * storaged_log: * @level: A #StoragedLogLevel. * @function: Pass #G_STRFUNC here. * @location: Pass #G_STRLOC here. * @format: printf()-style format. * @...: Arguments for format. * * Low-level logging function used by storaged_debug() and other macros. */ void storaged_log (StoragedLogLevel level, const gchar *function, const gchar *location, const gchar *format, ...) { va_list var_args; gchar *message; GTimeVal now; time_t now_time; struct tm *now_tm; gchar time_buf[128]; const gchar *level_str; const gchar *level_color_str; gint syslog_priority; static gboolean have_called_openlog = FALSE; gchar *thread_str; va_start (var_args, format); message = g_strdup_vprintf (format, var_args); va_end (var_args); G_LOCK (log_lock); if (!have_called_openlog) { openlog ("storaged", LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); have_called_openlog = TRUE; } g_get_current_time (&now); now_time = (time_t) now.tv_sec; now_tm = localtime (&now_time); strftime (time_buf, sizeof time_buf, "%H:%M:%S", now_tm); switch (level) { case STORAGED_LOG_LEVEL_DEBUG: level_str = "[DEBUG]"; syslog_priority = LOG_DEBUG; level_color_str = _color_get (_COLOR_FG_BLUE); break; case STORAGED_LOG_LEVEL_INFO: level_str = "[INFO]"; syslog_priority = LOG_INFO; level_color_str = _color_get (_COLOR_FG_CYAN); break; case STORAGED_LOG_LEVEL_NOTICE: level_str = "[NOTICE]"; syslog_priority = LOG_NOTICE; level_color_str = _color_get (_COLOR_FG_CYAN); break; case STORAGED_LOG_LEVEL_WARNING: level_str = "[WARNING]"; syslog_priority = LOG_WARNING; level_color_str = _color_get (_COLOR_FG_YELLOW); break; case STORAGED_LOG_LEVEL_ERROR: level_str = "[ERROR]"; syslog_priority = LOG_ERR; level_color_str = _color_get (_COLOR_FG_RED); break; default: g_assert_not_reached (); break; } thread_str = g_strdup_printf ("%d", (gint) syscall (SYS_gettid)); g_print ("%s%s%s.%03d:%s%s%s[%s]%s:%s%s%s:%s %s %s[%s, %s()]%s\n", _color_get (_COLOR_BOLD_ON), _color_get (_COLOR_FG_YELLOW), time_buf, (gint) now.tv_usec / 1000, _color_get (_COLOR_RESET), _color_get (_COLOR_FG_MAGENTA), _color_get (_COLOR_BOLD_ON), thread_str, _color_get (_COLOR_RESET), level_color_str, _color_get (_COLOR_BOLD_ON), level_str, _color_get (_COLOR_RESET), message, _color_get (_COLOR_FG_BLACK), location, function, _color_get (_COLOR_RESET)); if (level >= STORAGED_LOG_LEVEL_NOTICE) syslog (syslog_priority, "%s", message); g_free (message); G_UNLOCK (log_lock); }
static gboolean initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { UDisksClient *client = UDISKS_CLIENT (initable); gboolean ret; GList *objects, *l; GList *interfaces, *ll; ret = FALSE; /* This method needs to be idempotent to work with the singleton * pattern. See the docs for g_initable_init(). We implement this by * locking. */ G_LOCK (init_lock); if (client->is_initialized) { if (client->object_manager != NULL) ret = TRUE; else g_assert (client->initialization_error != NULL); goto out; } g_assert (client->initialization_error == NULL); client->context = g_main_context_get_thread_default (); if (client->context != NULL) g_main_context_ref (client->context); client->object_manager = udisks_object_manager_client_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "org.freedesktop.UDisks2", "/org/freedesktop/UDisks2", cancellable, &client->initialization_error); if (client->object_manager == NULL) goto out; /* init all proxies */ objects = g_dbus_object_manager_get_objects (client->object_manager); for (l = objects; l != NULL; l = l->next) { interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (l->data)); for (ll = interfaces; ll != NULL; ll = ll->next) { init_interface_proxy (client, G_DBUS_PROXY (ll->data)); } g_list_foreach (interfaces, (GFunc) g_object_unref, NULL); g_list_free (interfaces); } g_list_foreach (objects, (GFunc) g_object_unref, NULL); g_list_free (objects); g_signal_connect (client->object_manager, "object-added", G_CALLBACK (on_object_added), client); g_signal_connect (client->object_manager, "object-removed", G_CALLBACK (on_object_removed), client); g_signal_connect (client->object_manager, "interface-added", G_CALLBACK (on_interface_added), client); g_signal_connect (client->object_manager, "interface-removed", G_CALLBACK (on_interface_removed), client); g_signal_connect (client->object_manager, "interface-proxy-properties-changed", G_CALLBACK (on_interface_proxy_properties_changed), client); ret = TRUE; out: client->is_initialized = TRUE; if (!ret) { g_assert (client->initialization_error != NULL); g_propagate_error (error, g_error_copy (client->initialization_error)); } G_UNLOCK (init_lock); return ret; }
/* g_main_iterate () runs a single iteration of the mainloop, or, * if !dispatch checks to see if any sources need dispatching. * basic algorithm for dispatch=TRUE: * * 1) while the list of currently pending sources is non-empty, * we call (*dispatch) on those that are !IN_CALL or can_recurse, * removing sources from the list after each returns. * the return value of (*dispatch) determines whether the source * itself is kept alive. * * 2) call (*prepare) for sources that are not yet SOURCE_READY and * are !IN_CALL or can_recurse. a return value of TRUE determines * that the source would like to be dispatched immediatedly, it * is then flagged as SOURCE_READY. * * 3) poll with the pollfds from all sources at the priority of the * first source flagged as SOURCE_READY. if there are any sources * flagged as SOURCE_READY, we use a timeout of 0 or the minimum * of all timouts otherwise. * * 4) for each source !IN_CALL or can_recurse, if SOURCE_READY or * (*check) returns true, add the source to the pending list. * once one source returns true, stop after checking all sources * at that priority. * * 5) while the list of currently pending sources is non-empty, * call (*dispatch) on each source, removing the source * after the call. * */ static gboolean g_main_iterate (gboolean block, gboolean dispatch) { GHook *hook; GTimeVal current_time = { 0, 0 }; gint n_ready = 0; gint current_priority = 0; gint timeout; gboolean retval = FALSE; g_return_val_if_fail (!block || dispatch, FALSE); g_get_current_time (¤t_time); G_LOCK (main_loop); #ifdef G_THREADS_ENABLED if (poll_waiting) { g_warning("g_main_iterate(): main loop already active in another thread"); G_UNLOCK (main_loop); return FALSE; } #endif /* If recursing, finish up current dispatch, before starting over */ if (pending_dispatches) { if (dispatch) g_main_dispatch (¤t_time); G_UNLOCK (main_loop); return TRUE; } /* Prepare all sources */ timeout = block ? -1 : 0; hook = g_hook_first_valid (&source_list, TRUE); while (hook) { GSource *source = (GSource*) hook; gint source_timeout = -1; if ((n_ready > 0) && (source->priority > current_priority)) { g_hook_unref (&source_list, hook); break; } if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE)) { hook = g_hook_next_valid (&source_list, hook, TRUE); continue; } if (!(hook->flags & G_SOURCE_READY)) { gboolean (*prepare) (gpointer source_data, GTimeVal *current_time, gint *timeout, gpointer user_data); prepare = ((GSourceFuncs *) hook->func)->prepare; in_check_or_prepare++; G_UNLOCK (main_loop); if ((*prepare) (source->source_data, ¤t_time, &source_timeout, source->hook.data)) hook->flags |= G_SOURCE_READY; G_LOCK (main_loop); in_check_or_prepare--; } if (hook->flags & G_SOURCE_READY) { if (!dispatch) { g_hook_unref (&source_list, hook); G_UNLOCK (main_loop); return TRUE; } else { n_ready++; current_priority = source->priority; timeout = 0; } } if (source_timeout >= 0) { if (timeout < 0) timeout = source_timeout; else timeout = MIN (timeout, source_timeout); } hook = g_hook_next_valid (&source_list, hook, TRUE); } /* poll(), if necessary */ g_main_poll (timeout, n_ready > 0, current_priority); if (timeout != 0) g_get_current_time (¤t_time); /* Check to see what sources need to be dispatched */ n_ready = 0; hook = g_hook_first_valid (&source_list, TRUE); while (hook) { GSource *source = (GSource *)hook; if ((n_ready > 0) && (source->priority > current_priority)) { g_hook_unref (&source_list, hook); break; } if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE)) { hook = g_hook_next_valid (&source_list, hook, TRUE); continue; } if (!(hook->flags & G_SOURCE_READY)) { gboolean (*check) (gpointer source_data, GTimeVal *current_time, gpointer user_data); check = ((GSourceFuncs *) hook->func)->check; in_check_or_prepare++; G_UNLOCK (main_loop); if ((*check) (source->source_data, ¤t_time, source->hook.data)) hook->flags |= G_SOURCE_READY; G_LOCK (main_loop); in_check_or_prepare--; } if (hook->flags & G_SOURCE_READY) { if (dispatch) { hook->flags &= ~G_SOURCE_READY; g_hook_ref (&source_list, hook); pending_dispatches = g_slist_prepend (pending_dispatches, source); current_priority = source->priority; n_ready++; } else { g_hook_unref (&source_list, hook); G_UNLOCK (main_loop); return TRUE; } } hook = g_hook_next_valid (&source_list, hook, TRUE); } /* Now invoke the callbacks */ if (pending_dispatches) { pending_dispatches = g_slist_reverse (pending_dispatches); g_main_dispatch (¤t_time); retval = TRUE; } G_UNLOCK (main_loop); return retval; }
/* HOLDS: main_loop_lock */ static void g_main_poll (gint timeout, gboolean use_priority, gint priority) { #ifdef G_MAIN_POLL_DEBUG GTimer *poll_timer; #endif GPollFD *fd_array; GPollRec *pollrec; gint i; gint npoll; #ifdef G_THREADS_ENABLED #ifndef NATIVE_WIN32 if (wake_up_pipe[0] < 0) { if (pipe (wake_up_pipe) < 0) g_error ("Cannot create pipe main loop wake-up: %s\n", g_strerror (errno)); wake_up_rec.fd = wake_up_pipe[0]; wake_up_rec.events = G_IO_IN; g_main_add_poll_unlocked (0, &wake_up_rec); } #else if (wake_up_semaphore == NULL) { if ((wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL) g_error ("Cannot create wake-up semaphore: %d", GetLastError ()); wake_up_rec.fd = (gint) wake_up_semaphore; wake_up_rec.events = G_IO_IN; g_main_add_poll_unlocked (0, &wake_up_rec); } #endif #endif fd_array = g_new (GPollFD, n_poll_records); pollrec = poll_records; i = 0; while (pollrec && (!use_priority || priority >= pollrec->priority)) { if (pollrec->fd->events) { fd_array[i].fd = pollrec->fd->fd; /* In direct contradiction to the Unix98 spec, IRIX runs into * difficulty if you pass in POLLERR, POLLHUP or POLLNVAL * flags in the events field of the pollfd while it should * just ignoring them. So we mask them out here. */ fd_array[i].events = pollrec->fd->events & ~(G_IO_ERR|G_IO_HUP|G_IO_NVAL); fd_array[i].revents = 0; i++; } pollrec = pollrec->next; } #ifdef G_THREADS_ENABLED poll_waiting = TRUE; poll_changed = FALSE; #endif npoll = i; if (npoll || timeout != 0) { #ifdef G_MAIN_POLL_DEBUG g_print ("g_main_poll(%d) timeout: %d\r", npoll, timeout); poll_timer = g_timer_new (); #endif G_UNLOCK (main_loop); (*poll_func) (fd_array, npoll, timeout); G_LOCK (main_loop); #ifdef G_MAIN_POLL_DEBUG g_print ("g_main_poll(%d) timeout: %d - elapsed %12.10f seconds", npoll, timeout, g_timer_elapsed (poll_timer, NULL)); g_timer_destroy (poll_timer); pollrec = poll_records; i = 0; while (i < npoll) { if (pollrec->fd->events) { if (fd_array[i].revents) { g_print (" [%d:", fd_array[i].fd); if (fd_array[i].revents & G_IO_IN) g_print ("i"); if (fd_array[i].revents & G_IO_OUT) g_print ("o"); if (fd_array[i].revents & G_IO_PRI) g_print ("p"); if (fd_array[i].revents & G_IO_ERR) g_print ("e"); if (fd_array[i].revents & G_IO_HUP) g_print ("h"); if (fd_array[i].revents & G_IO_NVAL) g_print ("n"); g_print ("]"); } i++; } pollrec = pollrec->next; } g_print ("\n"); #endif } /* if (npoll || timeout != 0) */ #ifdef G_THREADS_ENABLED if (!poll_waiting) { #ifndef NATIVE_WIN32 gchar c; read (wake_up_pipe[0], &c, 1); #endif } else poll_waiting = FALSE; /* If the set of poll file descriptors changed, bail out * and let the main loop rerun */ if (poll_changed) { g_free (fd_array); return; } #endif pollrec = poll_records; i = 0; while (i < npoll) { if (pollrec->fd->events) { pollrec->fd->revents = fd_array[i].revents; i++; } pollrec = pollrec->next; } g_free (fd_array); }
static void on_dummy_monitor_destroy(GFile* gf, GFileMonitor* mon) { G_LOCK(hash); g_hash_table_remove(dummy_hash, gf); G_UNLOCK(hash); }
/** * g_content_type_guess: * @filename: (allow-none): a string, or %NULL * @data: (allow-none) (array length=data_size): a stream of data, or %NULL * @data_size: the size of @data * @result_uncertain: (allow-none) (out): return location for the certainty * of the result, or %NULL * * Guesses the content type based on example data. If the function is * uncertain, @result_uncertain will be set to %TRUE. Either @filename * or @data may be %NULL, in which case the guess will be based solely * on the other argument. * * Returns: a string indicating a guessed content type for the * given data. Free with g_free() */ gchar * g_content_type_guess (const gchar *filename, const guchar *data, gsize data_size, gboolean *result_uncertain) { char *basename; const char *name_mimetypes[10], *sniffed_mimetype; char *mimetype; int i; int n_name_mimetypes; int sniffed_prio; sniffed_prio = 0; n_name_mimetypes = 0; sniffed_mimetype = XDG_MIME_TYPE_UNKNOWN; if (result_uncertain) *result_uncertain = FALSE; /* our test suite and potentially other code used -1 in the past, which is * not documented and not allowed; guard against that */ g_return_val_if_fail (data_size != (gsize) -1, g_strdup (XDG_MIME_TYPE_UNKNOWN)); G_LOCK (gio_xdgmime); if (filename) { i = strlen (filename); if (filename[i - 1] == '/') { name_mimetypes[0] = "inode/directory"; name_mimetypes[1] = NULL; n_name_mimetypes = 1; if (result_uncertain) *result_uncertain = TRUE; } else { basename = g_path_get_basename (filename); n_name_mimetypes = xdg_mime_get_mime_types_from_file_name (basename, name_mimetypes, 10); g_free (basename); } } /* Got an extension match, and no conflicts. This is it. */ if (n_name_mimetypes == 1) { gchar *s = g_strdup (name_mimetypes[0]); G_UNLOCK (gio_xdgmime); return s; } if (data) { sniffed_mimetype = xdg_mime_get_mime_type_for_data (data, data_size, &sniffed_prio); if (sniffed_mimetype == XDG_MIME_TYPE_UNKNOWN && data && looks_like_text (data, data_size)) sniffed_mimetype = "text/plain"; /* For security reasons we don't ever want to sniff desktop files * where we know the filename and it doesn't have a .desktop extension. * This is because desktop files allow executing any application and * we don't want to make it possible to hide them looking like something * else. */ if (filename != NULL && strcmp (sniffed_mimetype, "application/x-desktop") == 0) sniffed_mimetype = "text/plain"; } if (n_name_mimetypes == 0) { if (sniffed_mimetype == XDG_MIME_TYPE_UNKNOWN && result_uncertain) *result_uncertain = TRUE; mimetype = g_strdup (sniffed_mimetype); } else { mimetype = NULL; if (sniffed_mimetype != XDG_MIME_TYPE_UNKNOWN) { if (sniffed_prio >= 80) /* High priority sniffing match, use that */ mimetype = g_strdup (sniffed_mimetype); else { /* There are conflicts between the name matches and we * have a sniffed type, use that as a tie breaker. */ for (i = 0; i < n_name_mimetypes; i++) { if ( xdg_mime_mime_type_subclass (name_mimetypes[i], sniffed_mimetype)) { /* This nametype match is derived from (or the same as) * the sniffed type). This is probably it. */ mimetype = g_strdup (name_mimetypes[i]); break; } } } } if (mimetype == NULL) { /* Conflicts, and sniffed type was no help or not there. * Guess on the first one */ mimetype = g_strdup (name_mimetypes[0]); if (result_uncertain) *result_uncertain = TRUE; } } G_UNLOCK (gio_xdgmime); return mimetype; }
static gboolean initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { GoaClient *client = GOA_CLIENT (initable); gboolean ret; ret = FALSE; /* This method needs to be idempotent to work with the singleton * pattern. See the docs for g_initable_init(). We implement this by * locking. */ G_LOCK (init_lock); if (client->is_initialized) { if (client->object_manager != NULL) ret = TRUE; else g_assert (client->initialization_error != NULL); goto out; } g_assert (client->initialization_error == NULL); client->object_manager = goa_object_manager_client_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "org.gnome.OnlineAccounts", "/org/gnome/OnlineAccounts", cancellable, &client->initialization_error); if (client->object_manager == NULL) goto out; g_signal_connect (client->object_manager, "object-added", G_CALLBACK (on_object_added), client); g_signal_connect (client->object_manager, "object-removed", G_CALLBACK (on_object_removed), client); g_signal_connect (client->object_manager, "interface-proxy-properties-changed", G_CALLBACK (on_interface_proxy_properties_changed), client); g_signal_connect (client->object_manager, "interface-added", G_CALLBACK (on_interface_added), client); g_signal_connect (client->object_manager, "interface-removed", G_CALLBACK (on_interface_removed), client); ret = TRUE; out: client->is_initialized = TRUE; if (!ret) { g_assert (client->initialization_error != NULL); g_propagate_error (error, g_error_copy (client->initialization_error)); } G_UNLOCK (init_lock); return ret; }