static gboolean grub_env_set(GPtrArray *pairs) { GSubprocess *sub; GError *error = NULL; gboolean res = FALSE; g_assert_cmpuint(pairs->len, >, 0); g_assert_nonnull(r_context()->config->grubenv_path); g_ptr_array_insert(pairs, 0, g_strdup("grub-editenv")); g_ptr_array_insert(pairs, 1, g_strdup(r_context()->config->grubenv_path)); g_ptr_array_insert(pairs, 2, g_strdup("set")); g_ptr_array_add(pairs, NULL); sub = g_subprocess_newv((const gchar * const *)pairs->pdata, G_SUBPROCESS_FLAGS_NONE, &error); if (!sub) { g_warning("starting grub-editenv failed: %s", error->message); g_clear_error(&error); goto out; } res = g_subprocess_wait_check(sub, NULL, &error); if (!res) { g_warning("grub-editenv failed: %s", error->message); g_clear_error(&error); goto out; } out: g_ptr_array_remove_index(pairs, pairs->len-1); g_ptr_array_remove_index(pairs, 2); g_ptr_array_remove_index(pairs, 1); g_ptr_array_remove_index(pairs, 0); return res; }
void g_ptr_array_insert_sorted (GPtrArray *array, GCompareFunc cmp, void *item) { guint index = bsearch (array, true, cmp, item); g_ptr_array_insert (array, index, item); }
Document* doc_load(const gchar* filename) { Document* doc = NULL; FILE* f = fopen(filename, "r"); if (f) { doc = doc_new(); doc->filename = g_strdup(filename); size_t allocated_len = 0; ssize_t len = 0; gchar* str = NULL; while ((len = getline(&str, &allocated_len, f)) > 0) { GString* s = g_slice_new(GString); if (str[len-1] == '\n') str[--len] = '\0'; // strip newline s->str = str; s->len = len; s->allocated_len = allocated_len; g_ptr_array_insert(doc->lines, -1, s); str = NULL; allocated_len = 0; } } return doc; }
static void g_ptr_array_insert_empty_array_at_pos (GPtrArray * array, gint pos) { GPtrArray *new_element; new_element = g_ptr_array_new (); g_ptr_array_insert (array, pos, new_element); }
static void message_received_any (ShpSlavePlugin * plugin, ShpBus * bus, ShpMessage * message) { ShpRest *self = SHP_REST (plugin); const gchar *source_path; ShpMessage *new_event; ShpMessage *old_event; gchar *timestamp; time_t t = time (NULL); struct tm *tm_struct = localtime (&t); g_debug ("rest: received event"); source_path = shp_message_get_source_path (message); if (!source_path) { g_debug ("rest: command event, not of interest"); return; } g_debug ("rest: storing event"); /* copy event and add timestamp to it */ new_event = shp_message_copy (message); timestamp = g_strdup_printf ("%d-%02d-%02d %02d-%02d-%02d", tm_struct->tm_year + 1900, tm_struct->tm_mon + 1, tm_struct->tm_mday, tm_struct->tm_hour, tm_struct->tm_min, tm_struct->tm_sec); shp_message_add_string (new_event, "rest.timestamp", timestamp); g_free (timestamp); g_mutex_lock (&self->mutex); /* remember old event if present */ old_event = g_hash_table_lookup (self->devices, source_path); if (old_event) { GPtrArray *arr; if (!g_hash_table_contains (self->history, source_path)) { arr = g_ptr_array_new_with_free_func (g_object_unref); g_hash_table_insert (self->history, g_strdup (source_path), arr); } else arr = g_hash_table_lookup (self->history, source_path); g_ptr_array_insert (arr, 0, g_object_ref (old_event)); if (arr->len > MAX_HISTORY_SIZE) g_ptr_array_set_size (arr, MAX_HISTORY_SIZE); } /* replace olf event with new one */ g_hash_table_insert (self->devices, g_strdup (source_path), new_event); g_mutex_unlock (&self->mutex); }
GOmxPort * g_omx_core_get_port (GOmxCore *core, const gchar *name, guint index) { GOmxPort *port = get_port (core, index); if (!port) { port = g_omx_port_new (core, name, index); g_ptr_array_insert (core->ports, index, port); } return port; }
static void _audit_log_helper (NMAuditManager *self, GPtrArray *fields, const char *file, guint line, const char *func, const char *op, gboolean result, gpointer subject_context, const char *reason) { AuditField op_field = { }, pid_field = { }, uid_field = { }; AuditField result_field = { }, reason_field = { }; gulong pid, uid; NMAuthSubject *subject = NULL; gs_unref_object NMAuthSubject *subject_free = NULL; _audit_field_init_string (&op_field, "op", op, FALSE, BACKEND_ALL); g_ptr_array_insert (fields, 0, &op_field); if (subject_context) { if (NM_IS_AUTH_SUBJECT (subject_context)) subject = subject_context; else if (G_IS_DBUS_METHOD_INVOCATION (subject_context)) { GDBusMethodInvocation *context = subject_context; subject = subject_free = nm_auth_subject_new_unix_process_from_context (context); } else g_warn_if_reached (); } if (subject && nm_auth_subject_is_unix_process (subject)) { pid = nm_auth_subject_get_unix_process_pid (subject); uid = nm_auth_subject_get_unix_process_uid (subject); if (pid != G_MAXULONG) { _audit_field_init_uint (&pid_field, "pid", pid, BACKEND_ALL); g_ptr_array_add (fields, &pid_field); } if (uid != G_MAXULONG) { _audit_field_init_uint (&uid_field, "uid", uid, BACKEND_ALL); g_ptr_array_add (fields, &uid_field); } } _audit_field_init_string (&result_field, "result", result ? "success" : "fail", FALSE, BACKEND_ALL); g_ptr_array_add (fields, &result_field); if (reason) { _audit_field_init_string (&reason_field, "reason", reason, FALSE, BACKEND_LOG); g_ptr_array_add (fields, &reason_field); } nm_audit_log (self, fields, file, line, func, result); }
GOmxPort * g_omx_core_new_port (GOmxCore *core, guint index) { GOmxPort *port = get_port (core, index); if (port) { GST_WARNING_OBJECT (core->object, "port %d already exists", index); return port; } port = g_omx_port_new (core, index); g_ptr_array_insert (core->ports, index, port); return port; }
GOmxPort * g_omx_core_setup_port (GOmxCore *core, OMX_PARAM_PORTDEFINITIONTYPE *omx_port) { GOmxPort *port; guint index; index = omx_port->nPortIndex; port = g_omx_core_get_port (core, index); if (!port) { port = g_omx_port_new (core); } g_omx_port_setup (port, omx_port); g_ptr_array_insert (core->ports, index, port); return port; }
/** * gstyle_palette_add_at_index: * @self: a #GstylePalette * @color: A #GstyleColor * @position: Position to insert the new color, from 0 to gstyle_palette_get_len() -1, * or -1 to append it * @error: (nullable): a #GError location or %NULL * * Add a #GstyleColor to the palette. * * Returns: %TRUE on succes, %FALSE otherwise. */ gboolean gstyle_palette_add_at_index (GstylePalette *self, GstyleColor *color, gint position, GError **error) { g_return_val_if_fail (GSTYLE_IS_PALETTE (self), FALSE); g_return_val_if_fail (GSTYLE_IS_COLOR (color), FALSE); /* If we are just after the last position, we in fact do an append */ if (position == self->colors->len) position = -1; if (position == -1 || (position == 0 && self->colors->len == 0) || (0 <= position && position < self->colors->len)) { g_object_ref (color); g_ptr_array_insert (self->colors, position, color); add_color_to_names_sets (self, color); gstyle_palette_set_changed (self, TRUE); position = (position == -1) ? self->colors->len - 1 : position; g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1); return TRUE; } else { g_warning ("Color inserted in palette '%s' at out-of-bounds position %i in (0, %i)\n", gstyle_palette_get_name (self), position, self->colors->len - 1); return FALSE; } }
int TextPointer::CompareToWithError (const TextPointer *pointer, MoonError *error) const { if (!verify_textpointer_in_document (this, error) || !verify_textpointer_in_document (pointer, error)) return -1; if (this->GetParent() == pointer->GetParent()) { DependencyObjectCollection *children = this->GetParentNode()->GetDocumentChildren(); if (children && children->GetCount() > 0) return compare_locations (this->GetLocation(), pointer->GetLocation()); else return this->ResolveLocation() - pointer->ResolveLocation(); } else { GPtrArray *this_array = g_ptr_array_new(); GPtrArray *pointer_array = g_ptr_array_new(); DependencyObject *el = GetParent(); while (el) { g_ptr_array_insert (this_array, 0, el); if (el->Is (Type::RICHTEXTBOX)) break; el = el->GetParent() ? el->GetParent()->GetParent() : NULL; if (!el) break; } el = pointer->GetParent(); while (el) { g_ptr_array_insert (pointer_array, 0, el); if (el->Is (Type::RICHTEXTBOX)) break; el = el->GetParent() ? el->GetParent()->GetParent() : NULL; if (!el) break; } guint32 count_to_compare = MIN (this_array->len, pointer_array->len); for (guint32 i = 0; i < count_to_compare; i ++) { DependencyObject *this_el = (DependencyObject*)g_ptr_array_index (this_array, i); DependencyObject *pointer_el = (DependencyObject*)g_ptr_array_index (pointer_array, i); if (this_el == pointer_el) continue; if (i == 0) { // this shouldn't happen... there shouldn't be a difference between two paths on the first element, since that should always be a RTB int rv = this_array->len < pointer_array->len ? -1 : 1; g_ptr_array_free (this_array, TRUE); g_ptr_array_free (pointer_array, TRUE); return rv; } /* at this point this_el and pointer_el are different. check index i-1's idea of their positions */ DependencyObject *common_parent = (DependencyObject*)g_ptr_array_index (this_array, i-1); IDocumentNode *common_parent_node = IDocumentNode::CastToIDocumentNode (common_parent); int this_index = common_parent_node->GetDocumentChildren()->IndexOf (Value (this_el)); int pointer_index = common_parent_node->GetDocumentChildren()->IndexOf (Value (pointer_el)); g_ptr_array_free (this_array, TRUE); g_ptr_array_free (pointer_array, TRUE); return this_index < pointer_index ? -1 : 1; } // if we make it here, it means we've run through // "count_to_compare" items that were identical, and // one of the paths is longer (so represents a child // of items[count_to_compare]. // so we need to figure out which array has more // elements, then compare that against the other // TextPointer's location if (count_to_compare < this_array->len) { // @this's parent is a child of pointer_array[count_to_compare-1] DependencyObject *parent = (DependencyObject*)g_ptr_array_index(pointer_array, count_to_compare - 1); IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent); guint32 child_index = parent_node->GetDocumentChildren()->IndexOf (Value ((DependencyObject*)g_ptr_array_index(this_array, count_to_compare))); return pointer->GetLocation() > child_index ? -1 : 1; } else if (count_to_compare < pointer_array->len) { // @pointer's parent is a child of this_array[count_to_compare-1] DependencyObject *parent = (DependencyObject*)g_ptr_array_index(this_array, count_to_compare - 1); IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent); guint32 child_index = parent_node->GetDocumentChildren()->IndexOf (Value ((DependencyObject*)g_ptr_array_index(pointer_array, count_to_compare))); return child_index >= this->GetLocation () ? -1 : 1; } } return -1; }
gboolean _gdk_win32_display_init_monitors (GdkWin32Display *win32_display) { GdkDisplay *display = GDK_DISPLAY (win32_display); GPtrArray *new_monitors; gint i; gboolean changed = FALSE; GdkWin32Monitor *primary_to_move = NULL; for (i = 0; i < win32_display->monitors->len; i++) GDK_WIN32_MONITOR (g_ptr_array_index (win32_display->monitors, i))->remove = TRUE; new_monitors = _gdk_win32_display_get_monitor_list (win32_display); for (i = 0; i < new_monitors->len; i++) { GdkWin32Monitor *w32_m; GdkMonitor *m; GdkWin32Monitor *w32_ex_monitor; GdkMonitor *ex_monitor; GdkRectangle geometry, ex_geometry; GdkRectangle workarea, ex_workarea; w32_m = GDK_WIN32_MONITOR (g_ptr_array_index (new_monitors, i)); m = GDK_MONITOR (w32_m); ex_monitor = _gdk_win32_display_find_matching_monitor (win32_display, m); w32_ex_monitor = GDK_WIN32_MONITOR (ex_monitor); if (ex_monitor == NULL) { w32_m->add = TRUE; changed = TRUE; continue; } w32_ex_monitor->remove = FALSE; if (i == 0) primary_to_move = w32_ex_monitor; gdk_monitor_get_geometry (m, &geometry); gdk_monitor_get_geometry (ex_monitor, &ex_geometry); gdk_monitor_get_workarea (m, &workarea); gdk_monitor_get_workarea (ex_monitor, &ex_workarea); if (memcmp (&workarea, &ex_workarea, sizeof (GdkRectangle)) != 0) { w32_ex_monitor->work_rect = workarea; changed = TRUE; } if (memcmp (&geometry, &ex_geometry, sizeof (GdkRectangle)) != 0) { gdk_monitor_set_size (ex_monitor, geometry.width, geometry.height); gdk_monitor_set_position (ex_monitor, geometry.x, geometry.y); changed = TRUE; } if (gdk_monitor_get_width_mm (m) != gdk_monitor_get_width_mm (ex_monitor) || gdk_monitor_get_height_mm (m) != gdk_monitor_get_height_mm (ex_monitor)) { gdk_monitor_set_physical_size (ex_monitor, gdk_monitor_get_width_mm (m), gdk_monitor_get_height_mm (m)); changed = TRUE; } if (g_strcmp0 (gdk_monitor_get_model (m), gdk_monitor_get_model (ex_monitor)) != 0) { gdk_monitor_set_model (ex_monitor, gdk_monitor_get_model (m)); changed = TRUE; } if (g_strcmp0 (gdk_monitor_get_manufacturer (m), gdk_monitor_get_manufacturer (ex_monitor)) != 0) { gdk_monitor_set_manufacturer (ex_monitor, gdk_monitor_get_manufacturer (m)); changed = TRUE; } if (gdk_monitor_get_refresh_rate (m) != gdk_monitor_get_refresh_rate (ex_monitor)) { gdk_monitor_set_refresh_rate (ex_monitor, gdk_monitor_get_refresh_rate (m)); changed = TRUE; } if (gdk_monitor_get_scale_factor (m) != gdk_monitor_get_scale_factor (ex_monitor)) { gdk_monitor_set_scale_factor (ex_monitor, gdk_monitor_get_scale_factor (m)); changed = TRUE; } if (gdk_monitor_get_subpixel_layout (m) != gdk_monitor_get_subpixel_layout (ex_monitor)) { gdk_monitor_set_subpixel_layout (ex_monitor, gdk_monitor_get_subpixel_layout (m)); changed = TRUE; } } for (i = win32_display->monitors->len - 1; i >= 0; i--) { GdkWin32Monitor *w32_ex_monitor; GdkMonitor *ex_monitor; w32_ex_monitor = GDK_WIN32_MONITOR (g_ptr_array_index (win32_display->monitors, i)); ex_monitor = GDK_MONITOR (w32_ex_monitor); if (!w32_ex_monitor->remove) continue; changed = TRUE; gdk_display_monitor_removed (display, ex_monitor); g_ptr_array_remove_index (win32_display->monitors, i); } for (i = 0; i < new_monitors->len; i++) { GdkWin32Monitor *w32_m; GdkMonitor *m; w32_m = GDK_WIN32_MONITOR (g_ptr_array_index (new_monitors, i)); m = GDK_MONITOR (w32_m); if (!w32_m->add) continue; gdk_display_monitor_added (display, m); if (i == 0) g_ptr_array_insert (win32_display->monitors, 0, g_object_ref (w32_m)); else g_ptr_array_add (win32_display->monitors, g_object_ref (w32_m)); } g_ptr_array_free (new_monitors, TRUE); if (primary_to_move) { g_ptr_array_remove (win32_display->monitors, g_object_ref (primary_to_move)); g_ptr_array_insert (win32_display->monitors, 0, primary_to_move); changed = TRUE; } return changed; }
static inline void insert_sorted (CbTweetModel *self, CbTweet *tweet) { int insert_pos = -1; if (self->reverse_order) { /* Special case. Just insert linearly here. We could improve this by doing the two special * cases from below and/or doing a binary search for the insertion position of course. */ int i; insert_pos = 0; /* reverse_order means that the tweet with the highest ID is at the bottom, * not the top of the model. I.e. the tweet with the lowest ID is at the * beginning of the model... */ for (i = 0; i < (int)self->tweets->len - 1; i ++) { CbTweet *cur = g_ptr_array_index (self->tweets, i); CbTweet *next = g_ptr_array_index (self->tweets, i + 1); if (cur->id <= tweet->id && next->id >= tweet->id) { insert_pos = i + 1; break; } } g_object_ref (tweet); g_ptr_array_insert (self->tweets, insert_pos, tweet); emit_items_changed (self, insert_pos, 0, 1); return; } if (tweet->id > self->max_id) { insert_pos = 0; } else if (tweet->id < self->min_id) { insert_pos = self->tweets->len; } else if (self->tweets->len == 0) { insert_pos = 0; } else { /* This case should be relatively rare in real life since * we only ever add tweets at the top or bottom of a list */ int i; /* int and not uint so empty lists are handled properly... */ for (i = 0; i < (int)self->tweets->len - 1; i ++) { CbTweet *cur = g_ptr_array_index (self->tweets, i); CbTweet *next = g_ptr_array_index (self->tweets, i + 1); if (cur->id >= tweet->id && next->id <= tweet->id) { insert_pos = i + 1; break; } } } if (insert_pos == -1) { /* This can happen if the same tweet gets inserted into an empty model twice. * Generally, we'd like to ignore double insertions, at least right now I can't * think of a good use case for it. (2017-06-13) */ return; } g_object_ref (tweet); g_ptr_array_insert (self->tweets, insert_pos, tweet); emit_items_changed (self, insert_pos, 0, 1); }
gboolean xdg_app_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; g_autoptr(XdgAppDeploy) app_deploy = NULL; g_autoptr(XdgAppDeploy) runtime_deploy = NULL; g_autoptr(GFile) app_files = NULL; g_autoptr(GFile) runtime_files = NULL; g_autoptr(GFile) app_id_dir = NULL; g_autoptr(GFile) app_cache_dir = NULL; g_autoptr(GFile) app_data_dir = NULL; g_autoptr(GFile) app_config_dir = NULL; g_autoptr(GFile) home = NULL; g_autoptr(GFile) user_font1 = NULL; g_autoptr(GFile) user_font2 = NULL; g_autoptr(XdgAppSessionHelper) session_helper = NULL; g_autofree char *runtime = NULL; g_autofree char *default_command = NULL; g_autofree char *runtime_ref = NULL; g_autofree char *app_ref = NULL; g_autofree char *doc_mount_path = NULL; g_autoptr(GKeyFile) metakey = NULL; g_autoptr(GKeyFile) runtime_metakey = NULL; g_autoptr(GPtrArray) argv_array = NULL; g_auto(GStrv) envp = NULL; g_autoptr(GPtrArray) dbus_proxy_argv = NULL; g_autofree char *monitor_path = NULL; const char *app; const char *branch = "master"; const char *command = "/bin/sh"; int i; int rest_argv_start, rest_argc; int sync_proxy_pipes[2]; g_autoptr(XdgAppContext) arg_context = NULL; g_autoptr(XdgAppContext) app_context = NULL; g_autoptr(XdgAppContext) overrides = NULL; g_autoptr(GDBusConnection) session_bus = NULL; context = g_option_context_new ("APP [args...] - Run an app"); rest_argc = 0; for (i = 1; i < argc; i++) { /* The non-option is the command, take it out of the arguments */ if (argv[i][0] != '-') { rest_argv_start = i; rest_argc = argc - i; argc = i; break; } } arg_context = xdg_app_context_new (); g_option_context_add_group (context, xdg_app_context_get_options (arg_context)); if (!xdg_app_option_context_parse (context, options, &argc, &argv, XDG_APP_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error)) return FALSE; if (rest_argc == 0) return usage_error (context, "APP must be specified", error); app = argv[rest_argv_start]; if (opt_branch) branch = opt_branch; if (!xdg_app_is_valid_name (app)) return xdg_app_fail (error, "'%s' is not a valid application name", app); if (!xdg_app_is_valid_branch (branch)) return xdg_app_fail (error, "'%s' is not a valid branch name", branch); app_ref = xdg_app_build_app_ref (app, branch, opt_arch); app_deploy = xdg_app_find_deploy_for_ref (app_ref, cancellable, error); if (app_deploy == NULL) return FALSE; metakey = xdg_app_deploy_get_metadata (app_deploy); argv_array = g_ptr_array_new_with_free_func (g_free); dbus_proxy_argv = g_ptr_array_new_with_free_func (g_free); g_ptr_array_add (argv_array, g_strdup (HELPER)); g_ptr_array_add (argv_array, g_strdup ("-l")); if (!xdg_app_run_add_extension_args (argv_array, metakey, app_ref, cancellable, error)) return FALSE; if (opt_runtime) runtime = opt_runtime; else { runtime = g_key_file_get_string (metakey, "Application", opt_devel ? "sdk" : "runtime", error); if (*error) return FALSE; } runtime_ref = g_build_filename ("runtime", runtime, NULL); runtime_deploy = xdg_app_find_deploy_for_ref (runtime_ref, cancellable, error); if (runtime_deploy == NULL) return FALSE; runtime_metakey = xdg_app_deploy_get_metadata (runtime_deploy); app_context = xdg_app_context_new (); if (!xdg_app_context_load_metadata (app_context, runtime_metakey, error)) return FALSE; if (!xdg_app_context_load_metadata (app_context, metakey, error)) return FALSE; overrides = xdg_app_deploy_get_overrides (app_deploy); xdg_app_context_merge (app_context, overrides); xdg_app_context_merge (app_context, arg_context); if (!xdg_app_run_add_extension_args (argv_array, runtime_metakey, runtime_ref, cancellable, error)) return FALSE; if ((app_id_dir = xdg_app_ensure_data_dir (app, cancellable, error)) == NULL) return FALSE; app_cache_dir = g_file_get_child (app_id_dir, "cache"); g_ptr_array_add (argv_array, g_strdup ("-B")); g_ptr_array_add (argv_array, g_strdup_printf ("/var/cache=%s", gs_file_get_path_cached (app_cache_dir))); app_data_dir = g_file_get_child (app_id_dir, "data"); g_ptr_array_add (argv_array, g_strdup ("-B")); g_ptr_array_add (argv_array, g_strdup_printf ("/var/data=%s", gs_file_get_path_cached (app_data_dir))); app_config_dir = g_file_get_child (app_id_dir, "config"); g_ptr_array_add (argv_array, g_strdup ("-B")); g_ptr_array_add (argv_array, g_strdup_printf ("/var/config=%s", gs_file_get_path_cached (app_config_dir))); app_files = xdg_app_deploy_get_files (app_deploy); runtime_files = xdg_app_deploy_get_files (runtime_deploy); default_command = g_key_file_get_string (metakey, "Application", "command", error); if (*error) return FALSE; if (opt_command) command = opt_command; else command = default_command; session_helper = xdg_app_session_helper_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, "org.freedesktop.XdgApp", "/org/freedesktop/XdgApp/SessionHelper", NULL, NULL); if (session_helper && xdg_app_session_helper_call_request_monitor_sync (session_helper, &monitor_path, NULL, NULL)) { g_ptr_array_add (argv_array, g_strdup ("-m")); g_ptr_array_add (argv_array, monitor_path); } else g_ptr_array_add (argv_array, g_strdup ("-r")); session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); if (session_bus) { g_autoptr (GError) local_error = NULL; g_autoptr (GDBusMessage) reply = NULL; g_autoptr (GDBusMessage) msg = g_dbus_message_new_method_call ("org.freedesktop.portal.Documents", "/org/freedesktop/portal/documents", "org.freedesktop.portal.Documents", "GetMountPoint"); g_dbus_message_set_body (msg, g_variant_new ("()")); reply = g_dbus_connection_send_message_with_reply_sync (session_bus, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 30000, NULL, NULL, NULL); if (reply) { if (g_dbus_message_to_gerror (reply, &local_error)) { g_warning ("Can't get document portal: %s\n", local_error->message); } else g_variant_get (g_dbus_message_get_body (reply), "(^ay)", &doc_mount_path); } } xdg_app_run_add_environment_args (argv_array, dbus_proxy_argv, doc_mount_path, app, app_context, app_id_dir); g_ptr_array_add (argv_array, g_strdup ("-b")); g_ptr_array_add (argv_array, g_strdup_printf ("/run/host/fonts=%s", SYSTEM_FONTS_DIR)); if (opt_devel) g_ptr_array_add (argv_array, g_strdup ("-c")); home = g_file_new_for_path (g_get_home_dir ()); user_font1 = g_file_resolve_relative_path (home, ".local/share/fonts"); user_font2 = g_file_resolve_relative_path (home, ".fonts"); if (g_file_query_exists (user_font1, NULL)) { g_autofree char *path = g_file_get_path (user_font1); g_ptr_array_add (argv_array, g_strdup ("-b")); g_ptr_array_add (argv_array, g_strdup_printf ("/run/host/user-fonts=%s", path)); } else if (g_file_query_exists (user_font2, NULL)) { g_autofree char *path = g_file_get_path (user_font2); g_ptr_array_add (argv_array, g_strdup ("-b")); g_ptr_array_add (argv_array, g_strdup_printf ("/run/host/user-fonts=%s", path)); } /* Must run this before spawning the dbus proxy, to ensure it ends up in the app cgroup */ xdg_app_run_in_transient_unit (app); if (dbus_proxy_argv->len > 0) { char x; if (pipe (sync_proxy_pipes) < 0) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Unable to create sync pipe"); return FALSE; } g_ptr_array_insert (dbus_proxy_argv, 0, g_strdup (DBUSPROXY)); g_ptr_array_insert (dbus_proxy_argv, 1, g_strdup_printf ("--fd=%d", sync_proxy_pipes[1])); g_ptr_array_add (dbus_proxy_argv, NULL); /* NULL terminate */ if (!g_spawn_async (NULL, (char **)dbus_proxy_argv->pdata, NULL, G_SPAWN_SEARCH_PATH, dbus_spawn_child_setup, GINT_TO_POINTER (sync_proxy_pipes[1]), NULL, error)) return FALSE; close (sync_proxy_pipes[1]); /* Sync with proxy, i.e. wait until its listening on the sockets */ if (read (sync_proxy_pipes[0], &x, 1) != 1) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Failed to sync with dbus proxy"); return FALSE; } g_ptr_array_add (argv_array, g_strdup ("-S")); g_ptr_array_add (argv_array, g_strdup_printf ("%d", sync_proxy_pipes[0])); } g_ptr_array_add (argv_array, g_strdup ("-a")); g_ptr_array_add (argv_array, g_file_get_path (app_files)); g_ptr_array_add (argv_array, g_strdup ("-I")); g_ptr_array_add (argv_array, g_strdup (app)); g_ptr_array_add (argv_array, g_file_get_path (runtime_files)); g_ptr_array_add (argv_array, g_strdup (command)); for (i = 1; i < rest_argc; i++) g_ptr_array_add (argv_array, g_strdup (argv[rest_argv_start + i])); g_ptr_array_add (argv_array, NULL); envp = g_get_environ (); envp = xdg_app_run_apply_env_default (envp); envp = xdg_app_run_apply_env_vars (envp, app_context); envp = xdg_app_run_apply_env_appid (envp, app_id_dir); if (execvpe (HELPER, (char **)argv_array->pdata, envp) == -1) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Unable to start app"); return FALSE; } /* Not actually reached... */ return TRUE; }
gboolean xdg_app_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **error) { GOptionContext *context; gboolean ret = FALSE; g_autoptr(GVariantBuilder) optbuilder = NULL; g_autoptr(GFile) deploy_base = NULL; g_autoptr(XdgAppDeploy) app_deploy = NULL; g_autoptr(XdgAppDeploy) runtime_deploy = NULL; g_autoptr(GFile) app_files = NULL; g_autoptr(GFile) runtime_files = NULL; g_autoptr(GFile) app_id_dir = NULL; g_autoptr(XdgAppSessionHelper) session_helper = NULL; g_autofree char *runtime = NULL; g_autofree char *default_command = NULL; g_autofree char *runtime_ref = NULL; g_autofree char *app_ref = NULL; g_autofree char *path = NULL; g_autoptr(GKeyFile) metakey = NULL; g_autoptr(GKeyFile) runtime_metakey = NULL; g_autoptr(GPtrArray) argv_array = NULL; glnx_strfreev char **envp = NULL; g_autoptr(GPtrArray) dbus_proxy_argv = NULL; g_autofree char *monitor_path = NULL; const char *app; const char *branch = "master"; const char *command = "/bin/sh"; int i; int rest_argv_start, rest_argc; int sync_proxy_pipes[2]; context = g_option_context_new ("APP [args...] - Run an app"); rest_argc = 0; for (i = 1; i < argc; i++) { /* The non-option is the command, take it out of the arguments */ if (argv[i][0] != '-') { rest_argv_start = i; rest_argc = argc - i; argc = i; break; } } if (!xdg_app_option_context_parse (context, options, &argc, &argv, XDG_APP_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error)) goto out; if (rest_argc == 0) { usage_error (context, "APP must be specified", error); goto out; } app = argv[rest_argv_start]; if (opt_branch) branch = opt_branch; if (!xdg_app_is_valid_name (app)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "'%s' is not a valid application name", app); goto out; } if (!xdg_app_is_valid_branch (branch)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "'%s' is not a valid branch name", branch); goto out; } app_ref = xdg_app_build_app_ref (app, branch, opt_arch); app_deploy = xdg_app_find_deploy_for_ref (app_ref, cancellable, error); if (app_deploy == NULL) goto out; metakey = xdg_app_deploy_get_metadata (app_deploy); argv_array = g_ptr_array_new_with_free_func (g_free); dbus_proxy_argv = g_ptr_array_new_with_free_func (g_free); g_ptr_array_add (argv_array, g_strdup (HELPER)); g_ptr_array_add (argv_array, g_strdup ("-l")); if (!add_extension_args (metakey, app_ref, argv_array, cancellable, error)) goto out; if (opt_runtime) runtime = opt_runtime; else { runtime = g_key_file_get_string (metakey, "Application", opt_devel ? "sdk" : "runtime", error); if (*error) goto out; } runtime_ref = g_build_filename ("runtime", runtime, NULL); runtime_deploy = xdg_app_find_deploy_for_ref (runtime_ref, cancellable, error); if (runtime_deploy == NULL) goto out; runtime_metakey = xdg_app_deploy_get_metadata (runtime_deploy); if (!add_extension_args (runtime_metakey, runtime_ref, argv_array, cancellable, error)) goto out; if ((app_id_dir = xdg_app_ensure_data_dir (app, cancellable, error)) == NULL) goto out; app_files = xdg_app_deploy_get_files (app_deploy); runtime_files = xdg_app_deploy_get_files (runtime_deploy); default_command = g_key_file_get_string (metakey, "Application", "command", error); if (*error) goto out; if (opt_command) command = opt_command; else command = default_command; session_helper = xdg_app_session_helper_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, "org.freedesktop.XdgApp.SessionHelper", "/org/freedesktop/XdgApp/SessionHelper", NULL, NULL); if (session_helper) { if (xdg_app_session_helper_call_request_monitor_sync (session_helper, &monitor_path, NULL, NULL)) { g_ptr_array_add (argv_array, g_strdup ("-m")); g_ptr_array_add (argv_array, monitor_path); } } if (!xdg_app_run_verify_environment_keys ((const char **)opt_forbid, error)) goto out; if (!xdg_app_run_verify_environment_keys ((const char **)opt_allow, error)) goto out; xdg_app_run_add_environment_args (argv_array, dbus_proxy_argv, app, runtime_metakey, metakey, (const char **)opt_allow, (const char **)opt_forbid); g_ptr_array_add (argv_array, g_strdup ("-b")); g_ptr_array_add (argv_array, g_strdup_printf ("/run/host/fonts=%s", SYSTEM_FONTS_DIR)); /* Must run this before spawning the dbus proxy, to ensure it ends up in the app cgroup */ xdg_app_run_in_transient_unit (app); if (dbus_proxy_argv->len > 0) { char x; if (pipe (sync_proxy_pipes) < 0) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Unable to create sync pipe"); goto out; } g_ptr_array_insert (dbus_proxy_argv, 0, g_strdup ("xdg-dbus-proxy")); g_ptr_array_insert (dbus_proxy_argv, 1, g_strdup_printf ("--fd=%d", sync_proxy_pipes[1])); g_ptr_array_add (dbus_proxy_argv, NULL); /* NULL terminate */ if (!g_spawn_async (NULL, (char **)dbus_proxy_argv->pdata, NULL, G_SPAWN_SEARCH_PATH, dbus_spawn_child_setup, GINT_TO_POINTER (sync_proxy_pipes[1]), NULL, error)) goto out; close (sync_proxy_pipes[1]); /* Sync with proxy, i.e. wait until its listening on the sockets */ if (read (sync_proxy_pipes[0], &x, 1) != 1) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Failed to sync with dbus proxy"); goto out; } g_ptr_array_add (argv_array, g_strdup ("-S")); g_ptr_array_add (argv_array, g_strdup_printf ("%d", sync_proxy_pipes[0])); } g_ptr_array_add (argv_array, g_strdup ("-a")); g_ptr_array_add (argv_array, g_file_get_path (app_files)); g_ptr_array_add (argv_array, g_strdup ("-I")); g_ptr_array_add (argv_array, g_strdup (app)); g_ptr_array_add (argv_array, g_file_get_path (runtime_files)); g_ptr_array_add (argv_array, g_strdup (command)); for (i = 1; i < rest_argc; i++) g_ptr_array_add (argv_array, g_strdup (argv[rest_argv_start + i])); g_ptr_array_add (argv_array, NULL); envp = g_get_environ (); envp = xdg_app_run_apply_env_default (envp); envp = xdg_app_run_apply_env_vars (envp, runtime_metakey); /* Load application environment overrides *after* runtime */ envp = xdg_app_run_apply_env_vars (envp, metakey); envp = xdg_app_run_apply_env_appid (envp, app_id_dir); if (execvpe (HELPER, (char **)argv_array->pdata, envp) == -1) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Unable to start app"); goto out; } /* Not actually reached... */ ret = TRUE; out: if (context) g_option_context_free (context); return ret; }