int main (int argc, char **argv) { GList *list = NULL; GList *categories = NULL; GOptionContext *context; gboolean prefer_local = FALSE; gboolean ret; gboolean show_results = FALSE; gboolean verbose = FALSE; guint64 refine_flags = GS_PLUGIN_REFINE_FLAGS_DEFAULT; gint i; gint cache_age = 0; gint repeat = 1; int status = 0; g_auto(GStrv) plugin_names = NULL; g_autoptr(GError) error = NULL; g_autoptr(GsDebug) debug = gs_debug_new (); g_autofree gchar *plugin_names_str = NULL; g_autofree gchar *refine_flags_str = NULL; g_autoptr(GsApp) app = NULL; g_autoptr(GFile) file = NULL; g_autoptr(GsPluginLoader) plugin_loader = NULL; g_autoptr(AsProfile) profile = NULL; g_autoptr(AsProfileTask) ptask = NULL; const GOptionEntry options[] = { { "show-results", '\0', 0, G_OPTION_ARG_NONE, &show_results, "Show the results for the action", NULL }, { "refine-flags", '\0', 0, G_OPTION_ARG_STRING, &refine_flags_str, "Set any refine flags required for the action", NULL }, { "repeat", '\0', 0, G_OPTION_ARG_INT, &repeat, "Repeat the action this number of times", NULL }, { "cache-age", '\0', 0, G_OPTION_ARG_INT, &cache_age, "Use this maximum cache age in seconds", NULL }, { "prefer-local", '\0', 0, G_OPTION_ARG_NONE, &prefer_local, "Prefer local file sources to AppStream", NULL }, { "plugin-names", '\0', 0, G_OPTION_ARG_STRING, &plugin_names_str, "Whitelist only these plugin names", NULL }, { "verbose", '\0', 0, G_OPTION_ARG_NONE, &verbose, "Show verbose debugging information", NULL }, { NULL} }; setlocale (LC_ALL, ""); g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); gtk_init (&argc, &argv); context = g_option_context_new (NULL); g_option_context_set_summary (context, "GNOME Software Test Program"); g_option_context_add_main_entries (context, options, NULL); g_option_context_add_group (context, gtk_get_option_group (TRUE)); ret = g_option_context_parse (context, &argc, &argv, &error); if (!ret) { g_print ("Failed to parse options: %s\n", error->message); goto out; } if (verbose) g_setenv ("GS_DEBUG", "1", TRUE); /* prefer local sources */ if (prefer_local) g_setenv ("GNOME_SOFTWARE_PREFER_LOCAL", "true", TRUE); /* parse any refine flags */ refine_flags = gs_cmd_parse_refine_flags (refine_flags_str, &error); if (refine_flags == G_MAXUINT64) { g_print ("Flag unknown: %s\n", error->message); goto out; } profile = as_profile_new (); ptask = as_profile_start_literal (profile, "GsCmd"); /* load plugins */ plugin_loader = gs_plugin_loader_new (); gs_plugin_loader_set_location (plugin_loader, "./plugins/.libs"); if (plugin_names_str != NULL) plugin_names = g_strsplit (plugin_names_str, ",", -1); ret = gs_plugin_loader_setup (plugin_loader, plugin_names, &error); if (!ret) { g_print ("Failed to setup plugins: %s\n", error->message); goto out; } gs_plugin_loader_dump_state (plugin_loader); /* do action */ if (argc == 2 && g_strcmp0 (argv[1], "installed") == 0) { for (i = 0; i < repeat; i++) { if (list != NULL) gs_app_list_free (list); list = gs_plugin_loader_get_installed (plugin_loader, refine_flags, NULL, &error); if (list == NULL) { ret = FALSE; break; } } } else if (argc == 3 && g_strcmp0 (argv[1], "search") == 0) { for (i = 0; i < repeat; i++) { if (list != NULL) gs_app_list_free (list); list = gs_plugin_loader_search (plugin_loader, argv[2], refine_flags, NULL, &error); if (list == NULL) { ret = FALSE; break; } } } else if (argc == 3 && g_strcmp0 (argv[1], "action-upgrade-download") == 0) { app = gs_app_new (argv[2]); gs_app_set_kind (app, AS_APP_KIND_OS_UPGRADE); ret = gs_plugin_loader_app_action (plugin_loader, app, GS_PLUGIN_LOADER_ACTION_UPGRADE_DOWNLOAD, NULL, &error); if (ret) gs_app_list_add (&list, app); } else if (argc == 3 && g_strcmp0 (argv[1], "refine") == 0) { app = gs_app_new (argv[2]); for (i = 0; i < repeat; i++) { ret = gs_plugin_loader_app_refine (plugin_loader, app, refine_flags, NULL, &error); if (!ret) break; } gs_app_list_add (&list, app); } else if (argc == 3 && g_strcmp0 (argv[1], "launch") == 0) { app = gs_app_new (argv[2]); for (i = 0; i < repeat; i++) { ret = gs_plugin_loader_app_action (plugin_loader, app, GS_PLUGIN_LOADER_ACTION_LAUNCH, NULL, &error); if (!ret) break; } } else if (argc == 3 && g_strcmp0 (argv[1], "filename-to-app") == 0) { file = g_file_new_for_path (argv[2]); app = gs_plugin_loader_file_to_app (plugin_loader, file, refine_flags, NULL, &error); if (app == NULL) { ret = FALSE; } else { gs_app_list_add (&list, app); } } else if (argc == 2 && g_strcmp0 (argv[1], "updates") == 0) { for (i = 0; i < repeat; i++) { if (list != NULL) gs_app_list_free (list); list = gs_plugin_loader_get_updates (plugin_loader, refine_flags, NULL, &error); if (list == NULL) { ret = FALSE; break; } } } else if (argc == 2 && g_strcmp0 (argv[1], "upgrades") == 0) { for (i = 0; i < repeat; i++) { if (list != NULL) gs_app_list_free (list); list = gs_plugin_loader_get_distro_upgrades (plugin_loader, refine_flags, NULL, &error); if (list == NULL) { ret = FALSE; break; } } } else if (argc == 2 && g_strcmp0 (argv[1], "sources") == 0) { list = gs_plugin_loader_get_sources (plugin_loader, refine_flags, NULL, &error); if (list == NULL) ret = FALSE; } else if (argc == 2 && g_strcmp0 (argv[1], "popular") == 0) { for (i = 0; i < repeat; i++) { if (list != NULL) gs_app_list_free (list); list = gs_plugin_loader_get_popular (plugin_loader, refine_flags, NULL, &error); if (list == NULL) { ret = FALSE; break; } } } else if (argc == 2 && g_strcmp0 (argv[1], "featured") == 0) { for (i = 0; i < repeat; i++) { if (list != NULL) gs_app_list_free (list); list = gs_plugin_loader_get_featured (plugin_loader, refine_flags, NULL, &error); if (list == NULL) { ret = FALSE; break; } } } else if (argc == 2 && g_strcmp0 (argv[1], "get-categories") == 0) { for (i = 0; i < repeat; i++) { if (categories != NULL) gs_app_list_free (categories); categories = gs_plugin_loader_get_categories (plugin_loader, refine_flags, NULL, &error); if (categories == NULL) { ret = FALSE; break; } } } else if (argc == 3 && g_strcmp0 (argv[1], "get-category-apps") == 0) { g_autoptr(GsCategory) category = NULL; g_auto(GStrv) split = NULL; split = g_strsplit (argv[2], "/", 2); if (g_strv_length (split) == 1) { category = gs_category_new (NULL, split[0], NULL); } else { g_autoptr(GsCategory) parent = NULL; parent = gs_category_new (NULL, split[0], NULL); category = gs_category_new (parent, split[1], NULL); } for (i = 0; i < repeat; i++) { if (list != NULL) gs_app_list_free (list); list = gs_plugin_loader_get_category_apps (plugin_loader, category, refine_flags, NULL, &error); if (list == NULL) { ret = FALSE; break; } } } else if (argc >= 2 && g_strcmp0 (argv[1], "refresh") == 0) { GsPluginRefreshFlags refresh_flags; refresh_flags = gs_cmd_refresh_flag_from_string (argv[2]); ret = gs_plugin_loader_refresh (plugin_loader, cache_age, refresh_flags, NULL, &error); } else { ret = FALSE; g_set_error_literal (&error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "Did not recognise option, use 'installed', " "'updates', 'popular', 'get-categories', " "'get-category-apps', 'filename-to-app', " "'sources', 'refresh', 'launch' or 'search'"); } if (!ret) { g_print ("Failed: %s\n", error->message); goto out; } if (show_results) { gs_cmd_show_results_apps (list); gs_cmd_show_results_categories (categories); } out: if (profile != NULL) as_profile_dump (profile); g_option_context_free (context); gs_app_list_free (list); gs_app_list_free (categories); return status; }
static void as_node_to_xml_string (GString *xml, guint depth_offset, const AsNode *n, AsNodeToXmlFlags flags) { AsNodeData *data = n->data; AsNode *c; const gchar *tag_str; const gchar *comment; guint depth = g_node_depth ((GNode *) n); gchar *attrs; /* comment */ comment = as_node_get_comment (n); if (comment != NULL) { guint i; g_auto(GStrv) split = NULL; /* do not put additional spacing for the root node */ if (depth_offset < g_node_depth ((GNode *) n) && (flags & AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE) > 0) g_string_append (xml, "\n"); if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_INDENT) > 0) as_node_add_padding (xml, depth - depth_offset); /* add each comment section */ split = g_strsplit (comment, "<&>", -1); for (i = 0; split[i] != NULL; i++) { g_string_append_printf (xml, "<!--%s-->", split[i]); if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE) > 0) g_string_append (xml, "\n"); } } /* root node */ if (data == NULL || as_node_get_tag (n) == AS_TAG_LAST) { if ((flags & AS_NODE_TO_XML_FLAG_SORT_CHILDREN) > 0) as_node_sort_children (n->children); for (c = n->children; c != NULL; c = c->next) as_node_to_xml_string (xml, depth_offset, c, flags); /* leaf node */ } else if (n->children == NULL) { if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_INDENT) > 0) as_node_add_padding (xml, depth - depth_offset); attrs = as_node_get_attr_string (data); tag_str = as_tag_data_get_name (data); if (data->cdata == NULL || data->cdata[0] == '\0') { g_string_append_printf (xml, "<%s%s/>", tag_str, attrs); } else { as_node_cdata_to_escaped (data); g_string_append_printf (xml, "<%s%s>%s</%s>", tag_str, attrs, data->cdata, tag_str); } if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE) > 0) g_string_append (xml, "\n"); g_free (attrs); /* node with children */ } else { if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_INDENT) > 0) as_node_add_padding (xml, depth - depth_offset); attrs = as_node_get_attr_string (data); tag_str = as_tag_data_get_name (data); g_string_append_printf (xml, "<%s%s>", tag_str, attrs); if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE) > 0) g_string_append (xml, "\n"); g_free (attrs); if ((flags & AS_NODE_TO_XML_FLAG_SORT_CHILDREN) > 0) as_node_sort_children (n->children); for (c = n->children; c != NULL; c = c->next) as_node_to_xml_string (xml, depth_offset, c, flags); if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_INDENT) > 0) as_node_add_padding (xml, depth - depth_offset); g_string_append_printf (xml, "</%s>", tag_str); if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE) > 0) g_string_append (xml, "\n"); } }
static gboolean install_packages_in_root (RpmOstreeTreeComposeContext *self, RpmOstreeContext *ctx, JsonObject *treedata, GFile *yumroot, char **packages, gboolean *out_unmodified, char **out_new_inputhash, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; guint progress_sigid; GFile *contextdir = self->treefile_context_dirs->pdata[0]; g_autoptr(RpmOstreeInstall) hifinstall = { 0, }; DnfContext *hifctx; g_autofree char *ret_new_inputhash = NULL; g_autoptr(GKeyFile) treespec = g_key_file_new (); JsonArray *enable_repos = NULL; JsonArray *add_files = NULL; /* TODO - uncomment this once we have SELinux working */ #if 0 g_autofree char *cache_repo_pathstr = glnx_fdrel_abspath (self->cachedir_dfd, "repo"); g_autoptr(GFile) cache_repo_path = g_file_new_for_path (cache_repo_pathstr); glnx_unref_object OstreeRepo *ostreerepo = ostree_repo_new (cache_repo_path); if (!g_file_test (cache_repo_pathstr, G_FILE_TEST_EXISTS)) { if (!ostree_repo_create (ostreerepo, OSTREE_REPO_MODE_BARE_USER, cancellable, error)) goto out; } #endif hifctx = rpmostree_context_get_hif (ctx); if (opt_proxy) dnf_context_set_http_proxy (hifctx, opt_proxy); /* Hack this here... see https://github.com/rpm-software-management/libhif/issues/53 * but in the future we won't be using librpm at all for unpack/scripts, so it won't * matter. */ { const char *debuglevel = getenv ("RPMOSTREE_RPM_VERBOSITY"); if (!debuglevel) debuglevel = "info"; dnf_context_set_rpm_verbosity (hifctx, debuglevel); rpmlogSetFile(NULL); } dnf_context_set_repo_dir (hifctx, gs_file_get_path_cached (contextdir)); /* By default, retain packages in addition to metadata with --cachedir */ if (opt_cachedir) dnf_context_set_keep_cache (hifctx, TRUE); if (opt_cache_only) dnf_context_set_cache_age (hifctx, G_MAXUINT); g_key_file_set_string (treespec, "tree", "ref", self->ref); g_key_file_set_string_list (treespec, "tree", "packages", (const char *const*)packages, g_strv_length (packages)); /* Some awful code to translate between JSON and GKeyFile */ if (json_object_has_member (treedata, "install-langs")) { JsonArray *a = json_object_get_array_member (treedata, "install-langs"); if (!set_keyfile_string_array_from_json (treespec, "tree", "install-langs", a, error)) goto out; } /* Bind the json \"repos\" member to the hif state, which looks at the * enabled= member of the repos file. By default we forcibly enable * only repos which are specified, ignoring the enabled= flag. */ if (!json_object_has_member (treedata, "repos")) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Treefile is missing required \"repos\" member"); goto out; } enable_repos = json_object_get_array_member (treedata, "repos"); if (!set_keyfile_string_array_from_json (treespec, "tree", "repos", enable_repos, error)) goto out; { gboolean docs = TRUE; if (!_rpmostree_jsonutil_object_get_optional_boolean_member (treedata, "documentation", &docs, error)) goto out; if (!docs) g_key_file_set_boolean (treespec, "tree", "documentation", FALSE); } { g_autoptr(GError) tmp_error = NULL; g_autoptr(RpmOstreeTreespec) treespec_value = rpmostree_treespec_new_from_keyfile (treespec, &tmp_error); g_assert_no_error (tmp_error); if (!rpmostree_context_setup (ctx, gs_file_get_path_cached (yumroot), "/", treespec_value, cancellable, error)) goto out; } /* --- Downloading metadata --- */ if (!rpmostree_context_download_metadata (ctx, cancellable, error)) goto out; if (!rpmostree_context_prepare_install (ctx, &hifinstall, cancellable, error)) goto out; rpmostree_print_transaction (hifctx); if (json_object_has_member (treedata, "add-files")) add_files = json_object_get_array_member (treedata, "add-files"); /* FIXME - just do a depsolve here before we compute download requirements */ if (!compute_checksum_from_treefile_and_goal (self, dnf_context_get_goal (hifctx), contextdir, add_files, &ret_new_inputhash, error)) goto out; /* Only look for previous checksum if caller has passed *out_unmodified */ if (self->previous_checksum && out_unmodified != NULL) { g_autoptr(GVariant) commit_v = NULL; g_autoptr(GVariant) commit_metadata = NULL; const char *previous_inputhash = NULL; if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_COMMIT, self->previous_checksum, &commit_v, error)) goto out; commit_metadata = g_variant_get_child_value (commit_v, 0); if (g_variant_lookup (commit_metadata, "rpmostree.inputhash", "&s", &previous_inputhash)) { if (strcmp (previous_inputhash, ret_new_inputhash) == 0) { *out_unmodified = TRUE; ret = TRUE; goto out; } } else g_print ("Previous commit found, but without rpmostree.inputhash metadata key\n"); } if (opt_dry_run) { ret = TRUE; goto out; } /* --- Downloading packages --- */ if (!rpmostree_context_download (ctx, hifinstall, cancellable, error)) goto out; { g_auto(GLnxConsoleRef) console = { 0, }; glnx_unref_object DnfState *hifstate = dnf_state_new (); progress_sigid = g_signal_connect (hifstate, "percentage-changed", G_CALLBACK (on_hifstate_percentage_changed), "Installing packages:"); glnx_console_lock (&console); if (!dnf_transaction_commit (dnf_context_get_transaction (hifctx), dnf_context_get_goal (hifctx), hifstate, error)) goto out; g_signal_handler_disconnect (hifstate, progress_sigid); } ret = TRUE; if (out_unmodified) *out_unmodified = FALSE; gs_transfer_out_value (out_new_inputhash, &ret_new_inputhash); out: return ret; }
gboolean as_app_parse_desktop_file (AsApp *app, const gchar *desktop_file, AsAppParseFlags flags, GError **error) { GKeyFileFlags kf_flags = G_KEY_FILE_KEEP_TRANSLATIONS; gchar *tmp; guint i; g_autoptr(GError) error_local = NULL; g_autofree gchar *app_id = NULL; g_autoptr(GKeyFile) kf = NULL; g_auto(GStrv) keys = NULL; /* load file */ kf = g_key_file_new (); if (flags & AS_APP_PARSE_FLAG_KEEP_COMMENTS) kf_flags |= G_KEY_FILE_KEEP_COMMENTS; if (!g_key_file_load_from_file (kf, desktop_file, kf_flags, &error_local)) { g_set_error (error, AS_APP_ERROR, AS_APP_ERROR_INVALID_TYPE, "Failed to parse %s: %s", desktop_file, error_local->message); return FALSE; } /* check this is a valid desktop file */ if (!g_key_file_has_group (kf, G_KEY_FILE_DESKTOP_GROUP)) { g_set_error (error, AS_APP_ERROR, AS_APP_ERROR_INVALID_TYPE, "Not a desktop file: no [%s]", G_KEY_FILE_DESKTOP_GROUP); return FALSE; } /* create app */ app_id = g_path_get_basename (desktop_file); as_app_set_kind (app, AS_APP_KIND_DESKTOP); /* is this really a web-app? */ if ((flags & AS_APP_PARSE_FLAG_USE_HEURISTICS) > 0) { g_autofree gchar *exec = NULL; exec = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL); if (exec != NULL) { if (g_str_has_prefix (exec, "epiphany --application-mode")) as_app_set_kind (app, AS_APP_KIND_WEB_APP); } } /* Ubuntu helpfully put the package name in the desktop file name */ tmp = g_strstr_len (app_id, -1, ":"); if (tmp != NULL) as_app_set_id (app, tmp + 1); else as_app_set_id (app, app_id); /* look at all the keys */ keys = g_key_file_get_keys (kf, G_KEY_FILE_DESKTOP_GROUP, NULL, error); if (keys == NULL) return FALSE; for (i = 0; keys[i] != NULL; i++) { if (!as_app_parse_file_key (app, kf, keys[i], flags, error)) return FALSE; if ((flags & AS_APP_PARSE_FLAG_USE_HEURISTICS) > 0) { if (!as_app_infer_file_key (app, kf, keys[i], error)) return FALSE; } } /* perform any fallbacks */ if ((flags & AS_APP_PARSE_FLAG_USE_FALLBACKS) > 0 && as_app_get_comment_size (app) == 0) { for (i = 0; keys[i] != NULL; i++) { if (!as_app_parse_file_key_fallback_comment (app, kf, keys[i], error)) return FALSE; } } /* all applications require icons */ if (as_app_get_icons(app)->len == 0) as_app_add_veto (app, "%s has no icon", app_id); return TRUE; }
static void test_strv (void) { g_auto(GStrv) val = g_strsplit("a:b:c", ":", -1); g_assert (val != NULL); }
static gboolean fu_altos_device_probe_bootloader (FuAltosDevice *self, GError **error) { g_autoptr(FuDeviceLocker) locker = NULL; g_auto(GStrv) lines = NULL; g_autoptr(GString) str = NULL; /* get tty for upload */ if (!fu_altos_device_find_tty (self, error)) return FALSE; locker = fu_device_locker_new_full (self, (FuDeviceLockerFunc) fu_altos_device_tty_open, (FuDeviceLockerFunc) fu_altos_device_tty_close, error); if (locker == NULL) return FALSE; /* get the version information */ if (!fu_altos_device_tty_write (self, "v\n", -1, error)) return FALSE; str = fu_altos_device_tty_read (self, 100, -1, error); if (str == NULL) return FALSE; /* parse each line */ lines = g_strsplit_set (str->str, "\n\r", -1); for (guint i = 0; lines[i] != NULL; i++) { /* ignore */ if (lines[i][0] == '\0') continue; if (g_str_has_prefix (lines[i], "manufacturer ")) continue; if (g_str_has_prefix (lines[i], "product ")) continue; /* we can flash firmware */ if (g_strcmp0 (lines[i], "altos-loader") == 0) { fu_device_remove_flag (FU_DEVICE (self), FWUPD_DEVICE_FLAG_NEEDS_BOOTLOADER); continue; } /* version number */ if (g_str_has_prefix (lines[i], "software-version ")) { fu_device_set_version (FU_DEVICE (self), lines[i] + 17); continue; } /* address base and bound */ if (g_str_has_prefix (lines[i], "flash-range ")) { g_auto(GStrv) addrs = g_strsplit (lines[i] + 17, " ", -1); self->addr_base = g_ascii_strtoull (addrs[0], NULL, 16); self->addr_bound = g_ascii_strtoull (addrs[1], NULL, 16); g_debug ("base: %x, bound: %x", (guint) self->addr_base, (guint) self->addr_bound); continue; } /* unknown line */ g_debug ("unknown data: '%s'", lines[i]); } return TRUE; }
/** * pk_package_sack_get_update_detail_cb: **/ static void pk_package_sack_get_update_detail_cb (GObject *source_object, GAsyncResult *res, PkPackageSackState *state) { PkClient *client = PK_CLIENT (source_object); PkUpdateDetail *item; guint i; PkPackage *package; g_autoptr(GError) error = NULL; g_autoptr(PkResults) results = NULL; g_autoptr(GPtrArray) update_details = NULL; /* get the results */ results = pk_client_generic_finish (client, res, &error); if (results == NULL) { g_warning ("failed to update_detail: %s", error->message); pk_package_sack_merge_bool_state_finish (state, error); return; } /* get the update_details */ update_details = pk_results_get_update_detail_array (results); if (update_details->len == 0) { error = g_error_new (1, 0, "no update details found!"); pk_package_sack_merge_bool_state_finish (state, error); return; } /* set data on each item */ for (i = 0; i < update_details->len; i++) { PkRestartEnum restart; PkUpdateStateEnum state_enum; g_autofree gchar *changelog = NULL; g_autofree gchar *issued = NULL; g_autofree gchar *obsoletes = NULL; g_autofree gchar *package_id = NULL; g_autofree gchar *updated = NULL; g_autofree gchar *updates = NULL; g_autofree gchar *update_text = NULL; g_auto(GStrv) bugzilla_urls = NULL; g_auto(GStrv) cve_urls = NULL; g_auto(GStrv) vendor_urls = NULL; item = g_ptr_array_index (update_details, i); g_object_get (item, "package-id", &package_id, "updates", &updates, "obsoletes", &obsoletes, "vendor-urls", &vendor_urls, "bugzilla-urls", &bugzilla_urls, "cve-urls", &cve_urls, "restart", &restart, "update-text", &update_text, "changelog", &changelog, "state", &state_enum, "issued", &issued, "updated", &updated, NULL); /* get package, and set data */ package = pk_package_sack_find_by_id (state->sack, package_id); if (package == NULL) { g_warning ("failed to find %s", package_id); continue; } /* set data */ g_object_set (package, "update-updates", updates, "update-obsoletes", obsoletes, "update-vendor-urls", vendor_urls, "update-bugzilla-urls", bugzilla_urls, "update-cve-urls", cve_urls, "update-restart", restart, "update-text", update_text, "update-changelog", changelog, "update-state", state_enum, "update-issued", issued, "update-updated", updated, NULL); g_object_unref (package); } /* all okay */ state->ret = TRUE; /* we're done */ pk_package_sack_merge_bool_state_finish (state, error); }
static gboolean _ostree_repo_list_refs_internal (OstreeRepo *self, gboolean cut_prefix, const char *refspec_prefix, GHashTable **out_all_refs, GCancellable *cancellable, GError **error) { g_autoptr(GHashTable) ret_all_refs = NULL; g_autofree char *remote = NULL; g_autofree char *ref_prefix = NULL; ret_all_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); if (refspec_prefix) { struct stat stbuf; const char *prefix_path; const char *path; if (!ostree_parse_refspec (refspec_prefix, &remote, &ref_prefix, error)) return FALSE; if (remote) { prefix_path = glnx_strjoina ("refs/remotes/", remote, "/"); path = glnx_strjoina (prefix_path, ref_prefix); } else { prefix_path = "refs/heads/"; path = glnx_strjoina (prefix_path, ref_prefix); } if (fstatat (self->repo_dir_fd, path, &stbuf, 0) < 0) { if (errno != ENOENT) return glnx_throw_errno (error); } else { if (S_ISDIR (stbuf.st_mode)) { glnx_fd_close int base_fd = -1; g_autoptr(GString) base_path = g_string_new (""); if (!cut_prefix) g_string_printf (base_path, "%s/", ref_prefix); if (!glnx_opendirat (self->repo_dir_fd, cut_prefix ? path : prefix_path, TRUE, &base_fd, error)) return FALSE; if (!enumerate_refs_recurse (self, remote, base_fd, base_path, base_fd, cut_prefix ? "." : ref_prefix, ret_all_refs, cancellable, error)) return FALSE; } else { glnx_fd_close int prefix_dfd = -1; if (!glnx_opendirat (self->repo_dir_fd, prefix_path, TRUE, &prefix_dfd, error)) return FALSE; if (!add_ref_to_set (remote, prefix_dfd, ref_prefix, ret_all_refs, cancellable, error)) return FALSE; } } } else { g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; g_autoptr(GString) base_path = g_string_new (""); glnx_fd_close int refs_heads_dfd = -1; if (!glnx_opendirat (self->repo_dir_fd, "refs/heads", TRUE, &refs_heads_dfd, error)) return FALSE; if (!enumerate_refs_recurse (self, NULL, refs_heads_dfd, base_path, refs_heads_dfd, ".", ret_all_refs, cancellable, error)) return FALSE; g_string_truncate (base_path, 0); if (!glnx_dirfd_iterator_init_at (self->repo_dir_fd, "refs/remotes", TRUE, &dfd_iter, error)) return FALSE; while (TRUE) { struct dirent *dent; glnx_fd_close int remote_dfd = -1; if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) return FALSE; if (!dent) break; if (dent->d_type != DT_DIR) continue; if (!glnx_opendirat (dfd_iter.fd, dent->d_name, TRUE, &remote_dfd, error)) return FALSE; if (!enumerate_refs_recurse (self, dent->d_name, remote_dfd, base_path, remote_dfd, ".", ret_all_refs, cancellable, error)) return FALSE; } } ot_transfer_out_value (out_all_refs, &ret_all_refs); return TRUE; }
static gboolean generate_all_deltas (OstreeRepo *repo, GPtrArray **unwanted_deltas, GCancellable *cancellable, GError **error) { g_autoptr(GHashTable) all_refs = NULL; g_autoptr(GHashTable) all_deltas_hash = NULL; g_autoptr(GHashTable) wanted_deltas_hash = NULL; g_autoptr(GPtrArray) all_deltas = NULL; int i; GHashTableIter iter; gpointer key, value; g_autoptr(GVariantBuilder) parambuilder = NULL; g_autoptr(GVariant) params = NULL; int n_spawned_delta_generate = 0; g_autoptr(GMainContextPopDefault) context = NULL; g_autoptr(GPtrArray) ignore_patterns = g_ptr_array_new_with_free_func ((GDestroyNotify)g_pattern_spec_free); g_print ("Generating static deltas\n"); parambuilder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); /* Fall back for 1 meg files */ g_variant_builder_add (parambuilder, "{sv}", "min-fallback-size", g_variant_new_uint32 (1)); params = g_variant_ref_sink (g_variant_builder_end (parambuilder)); if (!ostree_repo_list_static_delta_names (repo, &all_deltas, cancellable, error)) return FALSE; wanted_deltas_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); all_deltas_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); for (i = 0; i < all_deltas->len; i++) g_hash_table_insert (all_deltas_hash, g_strdup (g_ptr_array_index (all_deltas, i)), NULL); if (!ostree_repo_list_refs (repo, NULL, &all_refs, cancellable, error)) return FALSE; context = flatpak_main_context_new_default (); if (opt_static_delta_ignore_refs != NULL) { for (i = 0; opt_static_delta_ignore_refs[i] != NULL; i++) g_ptr_array_add (ignore_patterns, g_pattern_spec_new (opt_static_delta_ignore_refs[i])); } g_hash_table_iter_init (&iter, all_refs); while (g_hash_table_iter_next (&iter, &key, &value)) { const char *ref = key; const char *commit = value; g_autoptr(GVariant) variant = NULL; g_autoptr(GVariant) parent_variant = NULL; g_autofree char *parent_commit = NULL; g_autofree char *grandparent_commit = NULL; gboolean ignore_ref = FALSE; if (g_str_has_prefix (ref, "app/") || g_str_has_prefix (ref, "runtime/")) { g_auto(GStrv) parts = g_strsplit (ref, "/", 4); for (i = 0; i < ignore_patterns->len; i++) { GPatternSpec *pattern = g_ptr_array_index(ignore_patterns, i); if (g_pattern_match_string (pattern, parts[1])) { ignore_ref = TRUE; break; } } } else if (g_str_has_prefix (ref, "appstream/")) { /* Old appstream branch deltas poorly, and most users handle the new format */ ignore_ref = TRUE; } else if (g_str_has_prefix (ref, "appstream2/")) { /* Always delta this */ ignore_ref = FALSE; } else { /* Ignore unknown ref types */ ignore_ref = FALSE; } if (ignore_ref) { g_debug ("Ignoring deltas for ref %s", ref); continue; } if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, commit, &variant, NULL)) { g_warning ("Couldn't load commit %s", commit); continue; } /* From empty */ if (!g_hash_table_contains (all_deltas_hash, commit)) { if (!spawn_delta_generation (context, &n_spawned_delta_generate, repo, params, ref, NULL, commit, error)) return FALSE; } /* Mark this one as wanted */ g_hash_table_insert (wanted_deltas_hash, g_strdup (commit), GINT_TO_POINTER (1)); parent_commit = ostree_commit_get_parent (variant); if (parent_commit != NULL && !ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, parent_commit, &parent_variant, NULL)) { g_warning ("Couldn't load parent commit %s", parent_commit); continue; } /* From parent */ if (parent_variant != NULL) { g_autofree char *from_parent = g_strdup_printf ("%s-%s", parent_commit, commit); if (!g_hash_table_contains (all_deltas_hash, from_parent)) { if (!spawn_delta_generation (context, &n_spawned_delta_generate, repo, params, ref, parent_commit, commit, error)) return FALSE; } /* Mark parent-to-current as wanted */ g_hash_table_insert (wanted_deltas_hash, g_strdup (from_parent), GINT_TO_POINTER (1)); /* We also want to keep around the parent and the grandparent-to-parent deltas * because otherwise these will be deleted immediately which may cause a race if * someone is currently downloading them. * However, there is no need to generate these if they don't exist. */ g_hash_table_insert (wanted_deltas_hash, g_strdup (parent_commit), GINT_TO_POINTER (1)); grandparent_commit = ostree_commit_get_parent (parent_variant); if (grandparent_commit != NULL) g_hash_table_insert (wanted_deltas_hash, g_strdup_printf ("%s-%s", grandparent_commit, parent_commit), GINT_TO_POINTER (1)); } } while (n_spawned_delta_generate > 0) g_main_context_iteration (context, TRUE); *unwanted_deltas = g_ptr_array_new_with_free_func (g_free); for (i = 0; i < all_deltas->len; i++) { const char *delta = g_ptr_array_index (all_deltas, i); if (!g_hash_table_contains (wanted_deltas_hash, delta)) g_ptr_array_add (*unwanted_deltas, g_strdup (delta)); } return TRUE; }
/** * pk_backend_spawn_helper_va_list: **/ static gboolean pk_backend_spawn_helper_va_list (PkBackendSpawn *backend_spawn, PkBackendJob *job, const gchar *executable, va_list *args) { gboolean background; PkBackendSpawnPrivate *priv = backend_spawn->priv; PkSpawnArgvFlags flags = PK_SPAWN_ARGV_FLAGS_NONE; #if PK_BUILD_LOCAL const gchar *directory; #endif g_autoptr(GError) error = NULL; g_autofree gchar *filename = NULL; g_auto(GStrv) argv = NULL; g_auto(GStrv) envp = NULL; g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE); /* convert to a argv */ argv = pk_backend_spawn_va_list_to_argv (executable, args); if (argv == NULL) { g_warning ("argv NULL"); return FALSE; } #if PK_BUILD_LOCAL /* prefer the local version */ directory = priv->name; if (g_str_has_prefix (directory, "test_")) directory = "test"; filename = g_build_filename ("..", "backends", directory, "helpers", argv[PK_BACKEND_SPAWN_ARGV0], NULL); if (g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE) { g_debug ("local helper not found '%s'", filename); g_free (filename); filename = g_build_filename ("..", "backends", directory, argv[PK_BACKEND_SPAWN_ARGV0], NULL); } if (g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE) { g_debug ("local helper not found '%s'", filename); g_free (filename); filename = g_build_filename (DATADIR, "PackageKit", "helpers", priv->name, argv[PK_BACKEND_SPAWN_ARGV0], NULL); } #else filename = g_build_filename (DATADIR, "PackageKit", "helpers", priv->name, argv[PK_BACKEND_SPAWN_ARGV0], NULL); #endif g_debug ("using spawn filename %s", filename); /* replace the filename with the full path */ g_free (argv[PK_BACKEND_SPAWN_ARGV0]); argv[PK_BACKEND_SPAWN_ARGV0] = g_strdup (filename); /* copy idle setting from backend to PkSpawn instance */ background = pk_backend_job_get_background (job); g_object_set (priv->spawn, "background", (background == TRUE), NULL); #ifdef ENABLE_STRACE /* we can't reuse when using strace */ flags |= PK_SPAWN_ARGV_FLAGS_NEVER_REUSE; #endif priv->finished = FALSE; envp = pk_backend_spawn_get_envp (backend_spawn); if (!pk_spawn_argv (priv->spawn, argv, envp, flags, &error)) { pk_backend_job_error_code (priv->job, PK_ERROR_ENUM_INTERNAL_ERROR, "Spawn of helper '%s' failed: %s", argv[PK_BACKEND_SPAWN_ARGV0], error->message); pk_backend_job_finished (priv->job); return FALSE; } return TRUE; }
/** * fu_provider_udev_client_add: **/ static void fu_provider_udev_client_add (FuProviderUdev *provider_udev, GUdevDevice *device) { FuProviderUdevPrivate *priv = GET_PRIVATE (provider_udev); FuDevice *dev; const gchar *display_name; const gchar *guid; const gchar *product; const gchar *vendor; g_autofree gchar *guid_new = NULL; g_autofree gchar *id = NULL; g_autofree gchar *rom_fn = NULL; g_autofree gchar *version = NULL; g_auto(GStrv) split = NULL; g_autoptr(AsProfile) profile = as_profile_new (); g_autoptr(AsProfileTask) ptask = NULL; /* interesting device? */ guid = g_udev_device_get_property (device, "FWUPD_GUID"); if (guid == NULL) return; /* get data */ ptask = as_profile_start (profile, "FuProviderUdev:client-add{%s}", guid); g_debug ("adding udev device: %s", g_udev_device_get_sysfs_path (device)); /* is already in database */ id = fu_provider_udev_get_id (device); dev = g_hash_table_lookup (priv->devices, id); if (dev != NULL) { g_debug ("ignoring duplicate %s", id); return; } /* get the FW version from the BCD device revision */ product = g_udev_device_get_property (device, "PRODUCT"); if (product != NULL) { split = g_strsplit (product, "/", -1); if (g_strv_length (split) != 3) { g_warning ("env{PRODUCT} is invalid: %s", product); return; } version = g_strdup (split[2]); } /* no GUID from the ROM, so fix up the VID:PID */ if (!as_utils_guid_is_valid (guid)) { guid_new = as_utils_guid_from_string (guid); g_debug ("fixing GUID %s->%s", guid, guid_new); } else { guid_new = g_strdup (guid); } /* did we get enough data */ dev = fu_device_new (); fu_device_add_flag (dev, FU_DEVICE_FLAG_INTERNAL); fu_device_set_id (dev, id); fu_device_set_guid (dev, guid_new); display_name = g_udev_device_get_property (device, "FWUPD_MODEL"); if (display_name == NULL) display_name = g_udev_device_get_property (device, "ID_MODEL_FROM_DATABASE"); if (display_name != NULL) fu_device_set_name (dev, display_name); vendor = g_udev_device_get_property (device, "FWUPD_VENDOR"); if (vendor == NULL) vendor = g_udev_device_get_property (device, "ID_VENDOR_FROM_DATABASE"); if (vendor != NULL) fu_device_set_vendor (dev, vendor); if (version != NULL) fu_device_set_version (dev, version); /* get the FW version from the rom when unlocked */ rom_fn = g_build_filename (g_udev_device_get_sysfs_path (device), "rom", NULL); if (g_file_test (rom_fn, G_FILE_TEST_EXISTS)) { fu_device_set_metadata (dev, "RomFilename", rom_fn); fu_device_add_flag (dev, FU_DEVICE_FLAG_LOCKED); } /* insert to hash */ g_hash_table_insert (priv->devices, g_strdup (id), dev); fu_provider_device_add (FU_PROVIDER (provider_udev), dev); }
/** * pk_backend_spawn_parse_stdout: **/ static gboolean pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, PkBackendJob *job, const gchar *line, GError **error) { guint size; gchar *command; gchar *text; guint64 speed; guint64 download_size_remaining; PkInfoEnum info; PkRestartEnum restart; PkGroupEnum group; gulong package_size; gint percentage; PkErrorEnum error_enum; PkStatusEnum status_enum; PkRestartEnum restart_enum; PkSigTypeEnum sig_type; PkUpdateStateEnum update_state_enum; PkMediaTypeEnum media_type_enum; PkDistroUpgradeEnum distro_upgrade_enum; PkBackendSpawnPrivate *priv = backend_spawn->priv; g_auto(GStrv) sections = NULL; g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE); /* check if output line */ if (line == NULL) return FALSE; /* split by tab */ sections = g_strsplit (line, "\t", 0); command = sections[0]; /* get size */ size = g_strv_length (sections); if (g_strcmp0 (command, "package") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (pk_package_id_check (sections[2]) == FALSE) { g_set_error_literal (error, 1, 0, "invalid package_id"); return FALSE; } info = pk_info_enum_from_string (sections[1]); if (info == PK_INFO_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Info enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } g_strdelimit (sections[3], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[3], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[3]); return FALSE; } pk_backend_job_package (job, info, sections[2], sections[3]); } else if (g_strcmp0 (command, "details") == 0) { if (size != 8) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } group = pk_group_enum_from_string (sections[4]); /* ITS4: ignore, checked for overflow */ package_size = atol (sections[7]); if (package_size > 1073741824) { g_set_error_literal (error, 1, 0, "package size cannot be that large"); return FALSE; } g_strdelimit (sections[5], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[4], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[5]); return FALSE; } text = g_strdup (sections[5]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); pk_backend_job_details (job, sections[1], sections[2], sections[3], group, text, sections[6], package_size); g_free (text); } else if (g_strcmp0 (command, "finished") == 0) { if (size != 1) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } pk_backend_job_finished (job); priv->is_busy = FALSE; /* from this point on, we can start the kill timer */ pk_backend_spawn_start_kill_timer (backend_spawn); } else if (g_strcmp0 (command, "files") == 0) { g_auto(GStrv) tmp = NULL; if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } tmp = g_strsplit (sections[2], ";", -1); pk_backend_job_files (job, sections[1], tmp); } else if (g_strcmp0 (command, "repo-detail") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } g_strdelimit (sections[2], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[2], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[2]); return FALSE; } if (g_strcmp0 (sections[3], "true") == 0) { pk_backend_job_repo_detail (job, sections[1], sections[2], TRUE); } else if (g_strcmp0 (sections[3], "false") == 0) { pk_backend_job_repo_detail (job, sections[1], sections[2], FALSE); } else { g_set_error (error, 1, 0, "invalid qualifier '%s'", sections[3]); return FALSE; } } else if (g_strcmp0 (command, "updatedetail") == 0) { g_auto(GStrv) updates = NULL; g_auto(GStrv) obsoletes = NULL; g_auto(GStrv) vendor_urls = NULL; g_auto(GStrv) bugzilla_urls = NULL; g_auto(GStrv) cve_urls = NULL; if (size != 13) { g_set_error (error, 1, 0, "invalid command '%s', size %i", command, size); return FALSE; } restart = pk_restart_enum_from_string (sections[7]); if (restart == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[7]); return FALSE; } g_strdelimit (sections[12], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[12], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[12]); return FALSE; } update_state_enum = pk_update_state_enum_from_string (sections[10]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (sections[8], ";", '\n'); g_strdelimit (sections[9], ";", '\n'); updates = g_strsplit (sections[2], "&", -1); obsoletes = g_strsplit (sections[3], "&", -1); vendor_urls = g_strsplit (sections[4], ";", -1); bugzilla_urls = g_strsplit (sections[5], ";", -1); cve_urls = g_strsplit (sections[6], ";", -1); pk_backend_job_update_detail (job, sections[1], updates, obsoletes, vendor_urls, bugzilla_urls, cve_urls, restart, sections[8], sections[9], update_state_enum, sections[11], sections[12]); } else if (g_strcmp0 (command, "percentage") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (!pk_strtoint (sections[1], &percentage)) { g_set_error (error, 1, 0, "invalid percentage value %s", sections[1]); return FALSE; } else if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid percentage value %i", percentage); return FALSE; } else { pk_backend_job_set_percentage (job, percentage); } } else if (g_strcmp0 (command, "item-progress") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (!pk_package_id_check (sections[1])) { g_set_error (error, 1, 0, "invalid package_id"); return FALSE; } status_enum = pk_status_enum_from_string (sections[2]); if (status_enum == PK_STATUS_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Status enum not recognised, and hence ignored: '%s'", sections[2]); return FALSE; } if (!pk_strtoint (sections[3], &percentage)) { g_set_error (error, 1, 0, "invalid item-progress value %s", sections[3]); return FALSE; } if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid item-progress value %i", percentage); return FALSE; } pk_backend_job_set_item_progress (job, sections[1], status_enum, percentage); } else if (g_strcmp0 (command, "error") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } error_enum = pk_error_enum_from_string (sections[1]); if (error_enum == PK_ERROR_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Error enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } /* convert back all the ;'s to newlines */ text = g_strdup (sections[2]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); /* convert % else we try to format them */ g_strdelimit (text, "%", '$'); pk_backend_job_error_code (job, error_enum, "%s", text); g_free (text); } else if (g_strcmp0 (command, "requirerestart") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } restart_enum = pk_restart_enum_from_string (sections[1]); if (restart_enum == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } if (!pk_package_id_check (sections[2])) { g_set_error (error, 1, 0, "invalid package_id"); return FALSE; } pk_backend_job_require_restart (job, restart_enum, sections[2]); } else if (g_strcmp0 (command, "status") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } status_enum = pk_status_enum_from_string (sections[1]); if (status_enum == PK_STATUS_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Status enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } pk_backend_job_set_status (job, status_enum); } else if (g_strcmp0 (command, "speed") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (!pk_strtouint64 (sections[1], &speed)) { g_set_error (error, 1, 0, "failed to parse speed: '%s'", sections[1]); return FALSE; } pk_backend_job_set_speed (job, speed); } else if (g_strcmp0 (command, "download-size-remaining") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (!pk_strtouint64 (sections[1], &download_size_remaining)) { g_set_error (error, 1, 0, "failed to parse download_size_remaining: '%s'", sections[1]); return FALSE; } pk_backend_job_set_download_size_remaining (job, download_size_remaining); } else if (g_strcmp0 (command, "allow-cancel") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (g_strcmp0 (sections[1], "true") == 0) { pk_backend_job_set_allow_cancel (job, TRUE); } else if (g_strcmp0 (sections[1], "false") == 0) { pk_backend_job_set_allow_cancel (job, FALSE); } else { g_set_error (error, 1, 0, "invalid section '%s'", sections[1]); return FALSE; } } else if (g_strcmp0 (command, "no-percentage-updates") == 0) { if (size != 1) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } pk_backend_job_set_percentage (job, PK_BACKEND_PERCENTAGE_INVALID); } else if (g_strcmp0 (command, "repo-signature-required") == 0) { if (size != 9) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } sig_type = pk_sig_type_enum_from_string (sections[8]); if (sig_type == PK_SIGTYPE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Sig enum not recognised, and hence ignored: '%s'", sections[8]); return FALSE; } if (pk_strzero (sections[1])) { g_set_error (error, 1, 0, "package_id blank, and hence ignored: '%s'", sections[1]); return FALSE; } if (pk_strzero (sections[2])) { g_set_error (error, 1, 0, "repository name blank, and hence ignored: '%s'", sections[2]); return FALSE; } /* pass _all_ of the data */ pk_backend_job_repo_signature_required (job, sections[1], sections[2], sections[3], sections[4], sections[5], sections[6], sections[7], sig_type); } else if (g_strcmp0 (command, "eula-required") == 0) { if (size != 5) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (pk_strzero (sections[1])) { g_set_error (error, 1, 0, "eula_id blank, and hence ignored: '%s'", sections[1]); return FALSE; } if (pk_strzero (sections[2])) { g_set_error (error, 1, 0, "package_id blank, and hence ignored: '%s'", sections[2]); return FALSE; } if (pk_strzero (sections[4])) { g_set_error (error, 1, 0, "agreement name blank, and hence ignored: '%s'", sections[4]); return FALSE; } pk_backend_job_eula_required (job, sections[1], sections[2], sections[3], sections[4]); } else if (g_strcmp0 (command, "media-change-required") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } media_type_enum = pk_media_type_enum_from_string (sections[1]); if (media_type_enum == PK_MEDIA_TYPE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "media type enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } pk_backend_job_media_change_required (job, media_type_enum, sections[2], sections[3]); } else if (g_strcmp0 (command, "distro-upgrade") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } distro_upgrade_enum = pk_distro_upgrade_enum_from_string (sections[1]); if (distro_upgrade_enum == PK_DISTRO_UPGRADE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "distro upgrade enum not recognised, and hence ignored: '%s'", sections[1]); return FALSE; } g_strdelimit (sections[3], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[3], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[3]); return FALSE; } pk_backend_job_distro_upgrade (job, distro_upgrade_enum, sections[2], sections[3]); } else if (g_strcmp0 (command, "category") == 0) { if (size != 6) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); return FALSE; } if (g_strcmp0 (sections[1], sections[2]) == 0) { g_set_error_literal (error, 1, 0, "cat_id cannot be the same as parent_id"); return FALSE; } if (pk_strzero (sections[2])) { g_set_error_literal (error, 1, 0, "cat_id cannot not blank"); return FALSE; } if (pk_strzero (sections[3])) { g_set_error_literal (error, 1, 0, "name cannot not blank"); return FALSE; } g_strdelimit (sections[4], PK_UNSAFE_DELIMITERS, ' '); if (!g_utf8_validate (sections[4], -1, NULL)) { g_set_error (error, 1, 0, "text '%s' was not valid UTF8!", sections[4]); return FALSE; } if (pk_strzero (sections[5])) { g_set_error_literal (error, 1, 0, "icon cannot not blank"); return FALSE; } if (g_str_has_prefix (sections[5], "/")) { g_set_error (error, 1, 0, "icon '%s' should be a named icon, not a path", sections[5]); return FALSE; } pk_backend_job_category (job, sections[1], sections[2], sections[3], sections[4], sections[5]); } else { g_set_error (error, 1, 0, "invalid command '%s'", command); return FALSE; } return TRUE; }
gboolean flatpak_complete_install (FlatpakCompletion *completion) { g_autoptr(GOptionContext) context = NULL; g_autoptr(FlatpakDir) dir = NULL; g_autoptr(GError) error = NULL; g_auto(GStrv) refs = NULL; int i; context = g_option_context_new (""); if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL)) return FALSE; if (!opt_app && !opt_runtime) opt_app = opt_runtime = TRUE; flatpak_completion_debug ("install argc %d", completion->argc); switch (completion->argc) { case 0: case 1: /* REMOTE */ flatpak_complete_options (completion, global_entries); flatpak_complete_options (completion, options); flatpak_complete_options (completion, user_entries); { g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL); if (remotes == NULL) return FALSE; for (i = 0; remotes[i] != NULL; i++) flatpak_complete_word (completion, "%s ", remotes[i]); } break; case 2: /* Name */ refs = flatpak_dir_find_remote_refs (dir, completion->argv[1], NULL, NULL, opt_arch, opt_app, opt_runtime, NULL, &error); if (refs == NULL) flatpak_completion_debug ("find remote refs error: %s", error->message); for (i = 0; refs != NULL && refs[i] != NULL; i++) { g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL); if (parts) flatpak_complete_word (completion, "%s ", parts[1]); } break; case 3: /* Branch */ refs = flatpak_dir_find_remote_refs (dir, completion->argv[1], completion->argv[2], NULL, opt_arch, opt_app, opt_runtime, NULL, &error); if (refs == NULL) flatpak_completion_debug ("find remote refs error: %s", error->message); for (i = 0; refs != NULL && refs[i] != NULL; i++) { g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL); if (parts) flatpak_complete_word (completion, "%s ", parts[3]); } break; default: break; } return TRUE; }
gboolean flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; g_autoptr(FlatpakDir) dir = NULL; const char *repository; const char *name; const char *branch = NULL; g_autofree char *ref = NULL; gboolean is_app; g_autoptr(GFile) deploy_dir = NULL; g_autoptr(GPtrArray) related = NULL; int i; context = g_option_context_new ("REPOSITORY NAME [BRANCH] - Install an application or runtime"); if (!flatpak_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error)) return FALSE; if (opt_bundle) return install_bundle (dir, context, argc, argv, cancellable, error); if (argc < 3) return usage_error (context, "REPOSITORY and NAME must be specified", error); repository = argv[1]; name = argv[2]; if (argc >= 4) branch = argv[3]; if (!opt_app && !opt_runtime) opt_app = opt_runtime = TRUE; ref = flatpak_dir_find_remote_ref (dir, repository, name, branch, opt_arch, opt_app, opt_runtime, &is_app, cancellable, error); if (ref == NULL) return FALSE; deploy_dir = flatpak_dir_get_if_deployed (dir, ref, NULL, cancellable); if (deploy_dir != NULL) { g_auto(GStrv) parts = flatpak_decompose_ref (ref, error); return flatpak_fail (error, "%s %s, branch %s is already installed", is_app ? "App" : "Runtime", name, parts[3]); } if (!flatpak_dir_install (dir, opt_no_pull, opt_no_deploy, ref, repository, (const char **)opt_subpaths, NULL, cancellable, error)) return FALSE; if (!opt_no_related) { g_autoptr(GError) local_error = NULL; if (opt_no_pull) related = flatpak_dir_find_local_related (dir, ref, repository, NULL, &local_error); else related = flatpak_dir_find_remote_related (dir, ref, repository, NULL, &local_error); if (related == NULL) { g_printerr ("Warning: Problem looking for related refs: %s\n", local_error->message); g_clear_error (&local_error); } else { for (i = 0; i < related->len; i++) { FlatpakRelated *rel = g_ptr_array_index (related, i); g_auto(GStrv) parts = NULL; if (!rel->download) continue; parts = g_strsplit (rel->ref, "/", 0); g_print ("Installing related: %s\n", parts[1]); if (!flatpak_dir_install_or_update (dir, opt_no_pull, opt_no_deploy, rel->ref, repository, (const char **)rel->subpaths, NULL, cancellable, &local_error)) { g_printerr ("Warning: Failed to install related ref: %s\n", rel->ref); g_clear_error (&local_error); } } } } return TRUE; }
gboolean ot_admin_builtin_deploy (int argc, char **argv, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; const char *refspec; GOptionContext *context; glnx_unref_object OstreeSysroot *sysroot = NULL; GKeyFile *origin = NULL; glnx_unref_object OstreeRepo *repo = NULL; g_autoptr(GPtrArray) new_deployments = NULL; glnx_unref_object OstreeDeployment *new_deployment = NULL; glnx_unref_object OstreeDeployment *merge_deployment = NULL; g_autofree char *revision = NULL; __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL; context = g_option_context_new ("REFSPEC - Checkout revision REFSPEC as the new default deployment"); if (!ostree_admin_option_context_parse (context, options, &argc, &argv, OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER, &sysroot, cancellable, error)) goto out; if (argc < 2) { ot_util_usage_error (context, "REF/REV must be specified", error); goto out; } refspec = argv[1]; if (!ostree_sysroot_load (sysroot, cancellable, error)) goto out; if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) goto out; /* Find the currently booted deployment, if any; we will ensure it * is present in the new deployment list. */ if (!ot_admin_require_booted_deployment_or_osname (sysroot, opt_osname, cancellable, error)) { g_prefix_error (error, "Looking for booted deployment: "); goto out; } if (opt_origin_path) { origin = g_key_file_new (); if (!g_key_file_load_from_file (origin, opt_origin_path, 0, error)) goto out; } else { origin = ostree_sysroot_origin_new_from_refspec (sysroot, refspec); } if (!ostree_repo_resolve_rev (repo, refspec, FALSE, &revision, error)) goto out; merge_deployment = ostree_sysroot_get_merge_deployment (sysroot, opt_osname); /* Here we perform cleanup of any leftover data from previous * partial failures. This avoids having to call gs_shutil_rm_rf() * at random points throughout the process. * * TODO: Add /ostree/transaction file, and only do this cleanup if * we find it. */ if (!ostree_sysroot_prepare_cleanup (sysroot, cancellable, error)) { g_prefix_error (error, "Performing initial cleanup: "); goto out; } kargs = _ostree_kernel_args_new (); /* If they want the current kernel's args, they very likely don't * want the ones from the merge. */ if (opt_kernel_proc_cmdline) { if (!_ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error)) goto out; } else if (merge_deployment) { OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (merge_deployment); g_auto(GStrv) previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1); _ostree_kernel_args_append_argv (kargs, previous_args); } if (opt_kernel_argv) { _ostree_kernel_args_replace_argv (kargs, opt_kernel_argv); } if (opt_kernel_argv_append) { _ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append); } { g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs); if (!ostree_sysroot_deploy_tree (sysroot, opt_osname, revision, origin, merge_deployment, kargs_strv, &new_deployment, cancellable, error)) goto out; } if (!ostree_sysroot_simple_write_deployment (sysroot, opt_osname, new_deployment, merge_deployment, opt_retain ? OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN : 0, cancellable, error)) goto out; ret = TRUE; out: if (origin) g_key_file_unref (origin); if (context) g_option_context_free (context); return ret; }
gboolean gs_plugin_url_to_app (GsPlugin *plugin, GsAppList *list, const gchar *url, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); g_autofree gchar *scheme = NULL; g_autofree gchar *path = NULL; const gchar *id = NULL; const gchar * const *id_like = NULL; g_auto(GStrv) package_ids = NULL; g_autoptr(PkResults) results = NULL; g_autoptr(GsApp) app = NULL; g_autoptr(GsOsRelease) os_release = NULL; g_autoptr(GPtrArray) packages = NULL; g_autoptr(GPtrArray) details = NULL; g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin); path = gs_utils_get_url_path (url); /* only do this for apt:// on debian or debian-like distros */ os_release = gs_os_release_new (error); if (os_release == NULL) { g_prefix_error (error, "failed to determine OS information:"); return FALSE; } else { id = gs_os_release_get_id (os_release); id_like = gs_os_release_get_id_like (os_release); scheme = gs_utils_get_url_scheme (url); if (!(g_strcmp0 (scheme, "apt") == 0 && (g_strcmp0 (id, "debian") == 0 || g_strv_contains (id_like, "debian")))) { return TRUE; } } app = gs_app_new (NULL); gs_plugin_packagekit_set_packaging_format (plugin, app); gs_app_add_source (app, path); gs_app_set_kind (app, AS_APP_KIND_GENERIC); gs_app_set_bundle_kind (app, AS_BUNDLE_KIND_PACKAGE); package_ids = g_new0 (gchar *, 2); package_ids[0] = g_strdup (path); g_mutex_lock (&priv->client_mutex); results = pk_client_resolve (priv->client, pk_bitfield_from_enums (PK_FILTER_ENUM_NEWEST, PK_FILTER_ENUM_ARCH, -1), package_ids, cancellable, gs_packagekit_helper_cb, helper, error); g_mutex_unlock (&priv->client_mutex); if (!gs_plugin_packagekit_results_valid (results, error)) { g_prefix_error (error, "failed to resolve package_ids: "); return FALSE; } /* get results */ packages = pk_results_get_package_array (results); details = pk_results_get_details_array (results); if (packages->len >= 1) { if (gs_app_get_local_file (app) != NULL) return TRUE; gs_plugin_packagekit_resolve_packages_app (plugin, packages, app); gs_plugin_packagekit_refine_details_app (plugin, details, app); gs_app_list_add (list, app); } else { g_warning ("no results returned"); } return TRUE; }
gboolean gs_plugin_file_to_app (GsPlugin *plugin, GsAppList *list, GFile *file, GCancellable *cancellable, GError **error) { GsApp *app; guint i; g_autofree gchar *content_type = NULL; g_autofree gchar *output = NULL; g_auto(GStrv) argv = NULL; g_auto(GStrv) tokens = NULL; g_autoptr(GString) str = NULL; const gchar *mimetypes[] = { "application/vnd.debian.binary-package", NULL }; /* does this match any of the mimetypes we support */ content_type = gs_utils_get_content_type (file, cancellable, error); if (content_type == NULL) return FALSE; if (!g_strv_contains (mimetypes, content_type)) return TRUE; /* exec sync */ argv = g_new0 (gchar *, 5); argv[0] = g_strdup (DPKG_DEB_BINARY); argv[1] = g_strdup ("--showformat=${Package}\\n" "${Version}\\n" "${Installed-Size}\\n" "${Homepage}\\n" "${Description}"); argv[2] = g_strdup ("-W"); argv[3] = g_file_get_path (file); if (!g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, NULL, error)) { gs_utils_error_convert_gio (error); return FALSE; } /* parse output */ tokens = g_strsplit (output, "\n", 0); if (g_strv_length (tokens) < 5) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED, "dpkg-deb output format incorrect:\n\"%s\"\n", output); return FALSE; } /* create app */ app = gs_app_new (NULL); gs_app_set_state (app, AS_APP_STATE_AVAILABLE_LOCAL); gs_app_add_source (app, tokens[0]); gs_app_set_name (app, GS_APP_QUALITY_LOWEST, tokens[0]); gs_app_set_version (app, tokens[1]); gs_app_set_size_installed (app, 1024 * g_ascii_strtoull (tokens[2], NULL, 10)); gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, tokens[3]); gs_app_set_summary (app, GS_APP_QUALITY_LOWEST, tokens[4]); gs_app_set_kind (app, AS_APP_KIND_GENERIC); gs_app_set_metadata (app, "GnomeSoftware::Creator", gs_plugin_get_name (plugin)); /* multiline text */ str = g_string_new (""); for (i = 5; tokens[i] != NULL; i++) { if (g_strcmp0 (tokens[i], " .") == 0) { if (str->len > 0) g_string_truncate (str, str->len - 1); g_string_append (str, "\n"); continue; } g_strstrip (tokens[i]); g_string_append_printf (str, "%s ", tokens[i]); } if (str->len > 0) g_string_truncate (str, str->len - 1); gs_app_set_description (app, GS_APP_QUALITY_LOWEST, str->str); /* success */ gs_app_list_add (list, app); return TRUE; }
gchar * hdr_format_string (const gchar *data, gssize len) { g_autofree gchar *copy = NULL; g_autoptr(GString) out = NULL; g_autoptr(GArray) ar = NULL; g_auto(GStrv) chunks = NULL; guint long_ret = 0; guint long_ret_star = 0; guint long_ident = 0; guint long_ptype = 0; guint long_star = 0; ar = g_array_new (FALSE, FALSE, sizeof (Chunk)); g_array_set_clear_func (ar, (GDestroyNotify)clear_chunk); if (data == NULL || *data == 0) return g_strdup (""); if (len < 0) len = strlen (data); copy = g_strndup (data, len); chunks = g_strsplit (copy, ";", 0); for (guint i = 0; chunks[i]; i++) { g_strstrip (chunks[i]); if (!*chunks[i]) continue; if (!push_chunk (ar, chunks[i])) return NULL; } if (ar->len == 0) return NULL; out = g_string_new (NULL); #if 0 for (guint i = 0; i < ar->len; i++) { const Chunk *chunk = &g_array_index (ar, Chunk, i); } #endif for (guint i = 0; i < ar->len; i++) { const Chunk *chunk = &g_array_index (ar, Chunk, i); g_autofree gchar *rtype = NULL; guint n_star = 0; parse_rtype (chunk->return_type, &rtype, &n_star); long_ret = MAX (long_ret, strlen (rtype)); long_ret_star = MAX (long_ret_star, n_star); long_ident = MAX (long_ident, strlen (chunk->identifier)); for (const GSList *iter = chunk->params; iter; iter = iter->next) { Parameter *p = iter->data; long_star = MAX (long_star, p->n_star); if (p->type) long_ptype = MAX (long_ptype, strlen (p->type)); } } for (guint i = 0; i < ar->len; i++) { const Chunk *chunk = &g_array_index (ar, Chunk, i); guint n_star = 0; guint off; guint space; guint rlen; if (chunk->pre) g_string_append_printf (out, "%s\n", chunk->pre); off = out->len; if (chunk->return_type) { g_autofree gchar *rtype = NULL; parse_rtype (chunk->return_type, &rtype, &n_star); rlen = strlen (rtype); g_string_append (out, rtype); } else { g_string_append (out, "void"); rlen = 4; } for (guint j = rlen; j < long_ret; j++) g_string_append_c (out, ' '); g_string_append_c (out, ' '); for (guint j = 0; j < long_ret_star - n_star; j++) g_string_append_c (out, ' '); for (guint j = 0; j < n_star; j++) g_string_append_c (out, '*'); g_string_append (out, chunk->identifier); rlen = strlen (chunk->identifier); for (guint j = rlen; j < long_ident; j++) g_string_append_c (out, ' '); g_string_append (out, " ("); space = out->len - off; if (chunk->params == NULL) g_string_append (out, "void"); for (const GSList *iter = chunk->params; iter; iter = iter->next) { Parameter *p = iter->data; if (p->ellipsis) { g_string_append (out, "..."); break; } if (p->type == NULL) { g_warning ("Unexpected NULL value for type"); continue; } g_string_append (out, p->type); for (guint j = strlen (p->type); j < long_ptype; j++) g_string_append_c (out, ' '); g_string_append_c (out, ' '); for (guint j = p->n_star; j < long_star; j++) g_string_append_c (out, ' '); for (guint j = 0; j < p->n_star; j++) g_string_append_c (out, '*'); g_string_append (out, p->name); if (iter->next) { g_string_append (out, ",\n"); for (guint j = 0; j < space; j++) g_string_append_c (out, ' '); } } g_string_append_c (out, ')'); if (chunk->post) g_string_append_printf (out, " %s", chunk->post); g_string_append (out, ";\n"); } return g_string_free (g_steal_pointer (&out), FALSE); }
/** * as_app_parse_file_key: **/ static gboolean as_app_parse_file_key (AsApp *app, GKeyFile *kf, const gchar *key, AsAppParseFlags flags, GError **error) { gchar *dot = NULL; guint i; guint j; g_autofree gchar *locale = NULL; g_autofree gchar *tmp = NULL; g_auto(GStrv) list = NULL; /* NoDisplay */ if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY) == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && strcasecmp (tmp, "True") == 0) as_app_add_veto (app, "NoDisplay=true"); /* Type */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_TYPE) == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (g_strcmp0 (tmp, G_KEY_FILE_DESKTOP_TYPE_APPLICATION) != 0) { g_set_error_literal (error, AS_APP_ERROR, AS_APP_ERROR_INVALID_TYPE, "not an application"); return FALSE; } /* Icon */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_ICON) == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') { g_autoptr(AsIcon) icon = NULL; icon = as_icon_new (); if (g_path_is_absolute (tmp)) { as_icon_set_filename (icon, tmp); } else { /* work around a common mistake in desktop files */ dot = g_strstr_len (tmp, -1, "."); if (dot != NULL && (g_strcmp0 (dot, ".png") == 0 || g_strcmp0 (dot, ".xpm") == 0 || g_strcmp0 (dot, ".svg") == 0)) { *dot = '\0'; } } as_icon_set_name (icon, tmp); if (as_utils_is_stock_icon_name (tmp)) { as_icon_set_name (icon, tmp); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); } else if ((flags & AS_APP_PARSE_FLAG_USE_FALLBACKS) > 0 && _as_utils_is_stock_icon_name_fallback (tmp)) { as_icon_set_name (icon, tmp); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); } else { as_icon_set_kind (icon, AS_ICON_KIND_LOCAL); } as_app_add_icon (app, icon); } /* Categories */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_CATEGORIES) == 0) { list = g_key_file_get_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL); for (i = 0; list[i] != NULL; i++) { /* not a standard category */ if (g_str_has_prefix (list[i], "X-")) continue; /* check the category is valid */ if (!as_utils_is_category_id (list[i])) continue; /* ignore some useless keys */ if (g_strcmp0 (list[i], "GTK") == 0) continue; if (g_strcmp0 (list[i], "Qt") == 0) continue; if (g_strcmp0 (list[i], "KDE") == 0) continue; if (g_strcmp0 (list[i], "GNOME") == 0) continue; as_app_add_category (app, list[i]); } } else if (g_strcmp0 (key, "Keywords") == 0) { list = g_key_file_get_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL); for (i = 0; list[i] != NULL; i++) { g_auto(GStrv) kw_split = NULL; kw_split = g_strsplit (list[i], ",", -1); for (j = 0; kw_split[j] != NULL; j++) { if (kw_split[j][0] == '\0') continue; as_app_add_keyword (app, "C", kw_split[j]); } } } else if (g_str_has_prefix (key, "Keywords")) { locale = as_app_desktop_key_get_locale (key); list = g_key_file_get_locale_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, locale, NULL, NULL); for (i = 0; list[i] != NULL; i++) { g_auto(GStrv) kw_split = NULL; kw_split = g_strsplit (list[i], ",", -1); for (j = 0; kw_split[j] != NULL; j++) { if (kw_split[j][0] == '\0') continue; as_app_add_keyword (app, locale, kw_split[j]); } } } else if (g_strcmp0 (key, "MimeType") == 0) { list = g_key_file_get_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL); for (i = 0; list[i] != NULL; i++) as_app_add_mimetype (app, list[i]); } else if (g_strcmp0 (key, "X-AppInstall-Package") == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_add_pkgname (app, tmp); /* OnlyShowIn */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN) == 0) { /* if an app has only one entry, it's that desktop */ list = g_key_file_get_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL); if (g_strv_length (list) == 1) as_app_set_project_group (app, list[0]); /* Name */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_NAME) == 0 || g_strcmp0 (key, "_Name") == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_name (app, "C", tmp); /* Name[] */ } else if (g_str_has_prefix (key, G_KEY_FILE_DESKTOP_KEY_NAME)) { locale = as_app_desktop_key_get_locale (key); tmp = g_key_file_get_locale_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, locale, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_name (app, locale, tmp); /* Comment */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_COMMENT) == 0 || g_strcmp0 (key, "_Comment") == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_comment (app, "C", tmp); /* Comment[] */ } else if (g_str_has_prefix (key, G_KEY_FILE_DESKTOP_KEY_COMMENT)) { locale = as_app_desktop_key_get_locale (key); tmp = g_key_file_get_locale_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, locale, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_comment (app, locale, tmp); /* non-standard */ } else if (g_strcmp0 (key, "X-Ubuntu-Software-Center-Name") == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_name (app, "C", tmp); } else if (g_str_has_prefix (key, "X-Ubuntu-Software-Center-Name")) { locale = as_app_desktop_key_get_locale (key); tmp = g_key_file_get_locale_string (kf, G_KEY_FILE_DESKTOP_GROUP, "X-Ubuntu-Software-Center-Name", locale, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_name (app, locale, tmp); } return TRUE; }
/** * pk_offline_get_results: * @error: A #GError or %NULL * * Gets the last result of the offline transaction. * * Return value: (transfer full): A #PkResults, or %NULL * * Since: 0.9.6 **/ PkResults * pk_offline_get_results (GError **error) { gboolean ret; gboolean success; guint i; g_autoptr(GError) error_local = NULL; g_autofree gchar *data = NULL; g_autoptr(GKeyFile) file = NULL; g_autoptr(PkError) pk_error = NULL; g_autoptr(PkResults) results = NULL; g_auto(GStrv) package_ids = NULL; g_return_val_if_fail (error == NULL || *error == NULL, NULL); /* does not exist */ if (!g_file_test (PK_OFFLINE_RESULTS_FILENAME, G_FILE_TEST_EXISTS)) { g_set_error_literal (error, PK_OFFLINE_ERROR, PK_OFFLINE_ERROR_NO_DATA, "no update results available"); return NULL; } /* load data */ file = g_key_file_new (); ret = g_key_file_load_from_file (file, PK_OFFLINE_RESULTS_FILENAME, G_KEY_FILE_NONE, &error_local); if (!ret) { g_set_error (error, PK_OFFLINE_ERROR, PK_OFFLINE_ERROR_FAILED, "results file invalid: %s", error_local->message); return NULL; } /* add error */ results = pk_results_new (); success = g_key_file_get_boolean (file, PK_OFFLINE_RESULTS_GROUP, "Success", NULL); if (!success) { g_autofree gchar *details = NULL; g_autofree gchar *enum_str = NULL; pk_error = pk_error_new (); enum_str = g_key_file_get_string (file, PK_OFFLINE_RESULTS_GROUP, "ErrorCode", NULL); details = g_key_file_get_string (file, PK_OFFLINE_RESULTS_GROUP, "ErrorDetails", NULL); g_object_set (pk_error, "code", pk_error_enum_from_string (enum_str), "details", details, NULL); pk_results_set_error_code (results, pk_error); pk_results_set_exit_code (results, PK_EXIT_ENUM_FAILED); } else { pk_results_set_exit_code (results, PK_EXIT_ENUM_SUCCESS); } /* add packages */ data = g_key_file_get_string (file, PK_OFFLINE_RESULTS_GROUP, "Packages", NULL); if (data != NULL) { package_ids = g_strsplit (data, ",", -1); for (i = 0; package_ids[i] != NULL; i++) { g_autoptr(PkPackage) pkg = NULL; pkg = pk_package_new (); pk_package_set_info (pkg, PK_INFO_ENUM_UPDATING); if (!pk_package_set_id (pkg, package_ids[i], error)) return NULL; pk_results_add_package (results, pkg); } } return g_object_ref (results); }
static gboolean as_app_parse_file_key (AsApp *app, GKeyFile *kf, const gchar *key, AsAppParseFlags flags, GError **error) { guint i; guint j; g_autofree gchar *locale = NULL; g_autofree gchar *tmp = NULL; g_auto(GStrv) list = NULL; /* NoDisplay */ if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY) == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && strcasecmp (tmp, "True") == 0) as_app_add_veto (app, "NoDisplay=true"); /* Type */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_TYPE) == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (g_strcmp0 (tmp, G_KEY_FILE_DESKTOP_TYPE_APPLICATION) != 0) { g_set_error_literal (error, AS_APP_ERROR, AS_APP_ERROR_INVALID_TYPE, "not an application"); return FALSE; } /* Icon */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_ICON) == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') { g_autoptr(AsIcon) icon = NULL; icon = as_app_desktop_create_icon (app, tmp, flags); as_app_add_icon (app, icon); } /* Categories */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_CATEGORIES) == 0) { list = g_key_file_get_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL); for (i = 0; list[i] != NULL; i++) { const gchar *category_blacklist[] = { "X-GNOME-Settings-Panel", "X-Unity-Settings-Panel", NULL }; /* we have to veto these */ for (j = 0; category_blacklist[j] != NULL; j++) { if (g_strcmp0 (list[i], category_blacklist[j]) == 0) { as_app_add_veto (app, "Has category %s", category_blacklist[j]); } } /* check the category is valid */ if (!as_utils_is_category_id (list[i])) continue; /* ignore some useless keys */ if (g_strcmp0 (list[i], "GTK") == 0) continue; if (g_strcmp0 (list[i], "Qt") == 0) continue; if (g_strcmp0 (list[i], "KDE") == 0) continue; if (g_strcmp0 (list[i], "GNOME") == 0) continue; as_app_add_category (app, list[i]); } } else if (g_strcmp0 (key, "Keywords") == 0) { list = g_key_file_get_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL); for (i = 0; list[i] != NULL; i++) { g_auto(GStrv) kw_split = NULL; kw_split = g_strsplit (list[i], ",", -1); for (j = 0; kw_split[j] != NULL; j++) { if (kw_split[j][0] == '\0') continue; as_app_add_keyword (app, "C", kw_split[j]); } } } else if (g_str_has_prefix (key, "Keywords")) { locale = as_app_desktop_key_get_locale (key); if (flags & AS_APP_PARSE_FLAG_ONLY_NATIVE_LANGS && !g_strv_contains (g_get_language_names (), locale)) return TRUE; list = g_key_file_get_locale_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, locale, NULL, NULL); for (i = 0; list[i] != NULL; i++) { g_auto(GStrv) kw_split = NULL; kw_split = g_strsplit (list[i], ",", -1); for (j = 0; kw_split[j] != NULL; j++) { if (kw_split[j][0] == '\0') continue; as_app_add_keyword (app, locale, kw_split[j]); } } } else if (g_strcmp0 (key, "MimeType") == 0) { list = g_key_file_get_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL); for (i = 0; list[i] != NULL; i++) as_app_add_mimetype (app, list[i]); } else if (g_strcmp0 (key, "X-AppInstall-Package") == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_add_pkgname (app, tmp); /* OnlyShowIn */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN) == 0) { /* if an app has only one entry, it's that desktop */ list = g_key_file_get_string_list (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL); if (g_strv_length (list) == 1) as_app_set_project_group (app, list[0]); /* Name */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_NAME) == 0 || g_strcmp0 (key, "_Name") == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_name (app, "C", tmp); /* Name[] */ } else if (g_str_has_prefix (key, G_KEY_FILE_DESKTOP_KEY_NAME)) { locale = as_app_desktop_key_get_locale (key); if (flags & AS_APP_PARSE_FLAG_ONLY_NATIVE_LANGS && !g_strv_contains (g_get_language_names (), locale)) return TRUE; tmp = g_key_file_get_locale_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, locale, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_name (app, locale, tmp); /* Comment */ } else if (g_strcmp0 (key, G_KEY_FILE_DESKTOP_KEY_COMMENT) == 0 || g_strcmp0 (key, "_Comment") == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_comment (app, "C", tmp); /* Comment[] */ } else if (g_str_has_prefix (key, G_KEY_FILE_DESKTOP_KEY_COMMENT)) { locale = as_app_desktop_key_get_locale (key); if (flags & AS_APP_PARSE_FLAG_ONLY_NATIVE_LANGS && !g_strv_contains (g_get_language_names (), locale)) return TRUE; tmp = g_key_file_get_locale_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, locale, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_comment (app, locale, tmp); /* non-standard */ } else if (g_strcmp0 (key, "X-Ubuntu-Software-Center-Name") == 0) { tmp = g_key_file_get_string (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_name (app, "C", tmp); } else if (g_str_has_prefix (key, "X-Ubuntu-Software-Center-Name")) { locale = as_app_desktop_key_get_locale (key); if (flags & AS_APP_PARSE_FLAG_ONLY_NATIVE_LANGS && !g_strv_contains (g_get_language_names (), locale)) return TRUE; tmp = g_key_file_get_locale_string (kf, G_KEY_FILE_DESKTOP_GROUP, "X-Ubuntu-Software-Center-Name", locale, NULL); if (tmp != NULL && tmp[0] != '\0') as_app_set_name (app, locale, tmp); /* for Ubuntu */ } else if (g_strcmp0 (key, "X-AppStream-Ignore") == 0) { gboolean ret; ret = g_key_file_get_boolean (kf, G_KEY_FILE_DESKTOP_GROUP, key, NULL); if (ret) as_app_add_veto (app, "X-AppStream-Ignore"); } /* add any external attribute as metadata to the application */ if (flags & AS_APP_PARSE_FLAG_ADD_ALL_METADATA) as_app_parse_file_metadata (app, kf, key); return TRUE; }
/* TODO: Add a man page. */ gboolean ostree_builtin_create_usb (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; g_autoptr(OstreeAsyncProgress) progress = NULL; g_auto(GLnxConsoleRef) console = { 0, }; context = g_option_context_new ("MOUNT-PATH COLLECTION-ID REF [COLLECTION-ID REF...]"); /* Parse options. */ g_autoptr(OstreeRepo) src_repo = NULL; if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &src_repo, cancellable, error)) return FALSE; if (argc < 2) { ot_util_usage_error (context, "A MOUNT-PATH must be specified", error); return FALSE; } if (argc < 4) { ot_util_usage_error (context, "At least one COLLECTION-ID REF pair must be specified", error); return FALSE; } if (argc % 2 == 1) { ot_util_usage_error (context, "Only complete COLLECTION-ID REF pairs may be specified", error); return FALSE; } /* Open the USB stick, which must exist. Allow automounting and following symlinks. */ const char *mount_root_path = argv[1]; struct stat mount_root_stbuf; glnx_autofd int mount_root_dfd = -1; if (!glnx_opendirat (AT_FDCWD, mount_root_path, TRUE, &mount_root_dfd, error)) return FALSE; if (!glnx_fstat (mount_root_dfd, &mount_root_stbuf, error)) return FALSE; /* Read in the refs to add to the USB stick. */ g_autoptr(GPtrArray) refs = g_ptr_array_new_full (argc, (GDestroyNotify) ostree_collection_ref_free); for (gsize i = 2; i < argc; i += 2) { if (!ostree_validate_collection_id (argv[i], error) || !ostree_validate_rev (argv[i + 1], error)) return FALSE; g_ptr_array_add (refs, ostree_collection_ref_new (argv[i], argv[i + 1])); } /* Open the destination repository on the USB stick or create it if it doesn’t exist. * Check it’s below @mount_root_path, and that it’s not the same as the source * repository. * * If the destination file system supports xattrs (for example, ext4), we use * a BARE_USER repository; if it doesn’t (for example, FAT), we use ARCHIVE. * In either case, we want a lossless repository. */ const char *dest_repo_path = (opt_destination_repo != NULL) ? opt_destination_repo : ".ostree/repo"; if (!glnx_shutil_mkdir_p_at (mount_root_dfd, dest_repo_path, 0755, cancellable, error)) return FALSE; OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER; if (TEMP_FAILURE_RETRY (fgetxattr (mount_root_dfd, "user.test", NULL, 0)) < 0 && (errno == ENOTSUP || errno == EOPNOTSUPP)) mode = OSTREE_REPO_MODE_ARCHIVE; g_debug ("%s: Creating repository in mode %u", G_STRFUNC, mode); g_autoptr(OstreeRepo) dest_repo = ostree_repo_create_at (mount_root_dfd, dest_repo_path, mode, NULL, cancellable, error); if (dest_repo == NULL) return FALSE; struct stat dest_repo_stbuf; if (!glnx_fstat (ostree_repo_get_dfd (dest_repo), &dest_repo_stbuf, error)) return FALSE; if (dest_repo_stbuf.st_dev != mount_root_stbuf.st_dev) { ot_util_usage_error (context, "--destination-repo must be a descendent of MOUNT-PATH", error); return FALSE; } if (ostree_repo_equal (src_repo, dest_repo)) { ot_util_usage_error (context, "--destination-repo must not be the source repository", error); return FALSE; } if (!ostree_ensure_repo_writable (dest_repo, error)) return FALSE; if (opt_disable_fsync) ostree_repo_set_disable_fsync (dest_repo, TRUE); /* Copy across all of the collection–refs to the destination repo. */ GVariantBuilder refs_builder; g_variant_builder_init (&refs_builder, G_VARIANT_TYPE ("a(sss)")); for (gsize i = 0; i < refs->len; i++) { const OstreeCollectionRef *ref = g_ptr_array_index (refs, i); g_variant_builder_add (&refs_builder, "(sss)", ref->collection_id, ref->ref_name, ""); } { GVariantBuilder builder; g_autoptr(GVariant) opts = NULL; OstreeRepoPullFlags flags = OSTREE_REPO_PULL_FLAGS_MIRROR; glnx_console_lock (&console); if (console.is_tty) progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console); g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&builder, "{s@v}", "collection-refs", g_variant_new_variant (g_variant_builder_end (&refs_builder))); g_variant_builder_add (&builder, "{s@v}", "flags", g_variant_new_variant (g_variant_new_int32 (flags))); g_variant_builder_add (&builder, "{s@v}", "depth", g_variant_new_variant (g_variant_new_int32 (0))); opts = g_variant_ref_sink (g_variant_builder_end (&builder)); g_autofree char *src_repo_uri = g_file_get_uri (ostree_repo_get_path (src_repo)); if (!ostree_repo_pull_with_options (dest_repo, src_repo_uri, opts, progress, cancellable, error)) { ostree_repo_abort_transaction (dest_repo, cancellable, NULL); return FALSE; } if (progress != NULL) ostree_async_progress_finish (progress); } /* Ensure a summary file is present to make it easier to look up commit checksums. */ /* FIXME: It should be possible to work without this, but find_remotes_cb() in * ostree-repo-pull.c currently assumes a summary file (signed or unsigned) is * present. */ struct stat stbuf; if (!glnx_fstatat_allow_noent (ostree_repo_get_dfd (dest_repo), "summary", &stbuf, 0, error)) return FALSE; if (errno == ENOENT && !ostree_repo_regenerate_summary (dest_repo, NULL, cancellable, error)) return FALSE; /* Add the symlinks .ostree/repos.d/@symlink_name → @dest_repo_path, unless * the @dest_repo_path is a well-known one like ostree/repo, in which case no * symlink is necessary; #OstreeRepoFinderMount always looks there. */ if (!g_str_equal (dest_repo_path, "ostree/repo") && !g_str_equal (dest_repo_path, ".ostree/repo")) { if (!glnx_shutil_mkdir_p_at (mount_root_dfd, ".ostree/repos.d", 0755, cancellable, error)) return FALSE; /* Find a unique name for the symlink. If a symlink already targets * @dest_repo_path, use that and don’t create a new one. */ GLnxDirFdIterator repos_iter; gboolean need_symlink = TRUE; if (!glnx_dirfd_iterator_init_at (mount_root_dfd, ".ostree/repos.d", TRUE, &repos_iter, error)) return FALSE; while (TRUE) { struct dirent *repo_dent; if (!glnx_dirfd_iterator_next_dent (&repos_iter, &repo_dent, cancellable, error)) return FALSE; if (repo_dent == NULL) break; /* Does the symlink already point to this repository? (Or is the * repository itself present in repos.d?) We already guarantee that * they’re on the same device. */ if (repo_dent->d_ino == dest_repo_stbuf.st_ino) { need_symlink = FALSE; break; } } /* If we need a symlink, find a unique name for it and create it. */ if (need_symlink) { /* Relative to .ostree/repos.d. */ g_autofree char *relative_dest_repo_path = g_build_filename ("..", "..", dest_repo_path, NULL); guint i; const guint max_attempts = 100; for (i = 0; i < max_attempts; i++) { g_autofree char *symlink_path = g_strdup_printf (".ostree/repos.d/%02u-generated", i); int ret = TEMP_FAILURE_RETRY (symlinkat (relative_dest_repo_path, mount_root_dfd, symlink_path)); if (ret < 0 && errno != EEXIST) return glnx_throw_errno_prefix (error, "symlinkat(%s → %s)", symlink_path, relative_dest_repo_path); else if (ret >= 0) break; } if (i == max_attempts) return glnx_throw (error, "Could not find an unused symlink name for the repository"); } } /* Report success to the user. */ g_autofree char *src_repo_path = g_file_get_path (ostree_repo_get_path (src_repo)); g_print ("Copied %u/%u refs successfully from ‘%s’ to ‘%s’ repository in ‘%s’.\n", refs->len, refs->len, src_repo_path, dest_repo_path, mount_root_path); return TRUE; }
static void test_g_cond (void) { g_auto(GCond) val; g_cond_init (&val); }
gboolean ostree_builtin_pull_local (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autoptr(GOptionContext) context = NULL; g_autoptr(OstreeRepo) repo = NULL; int i; const char *src_repo_arg; g_autofree char *src_repo_uri = NULL; g_autoptr(OstreeAsyncProgress) progress = NULL; g_autoptr(GPtrArray) refs_to_fetch = NULL; OstreeRepoPullFlags pullflags = 0; context = g_option_context_new ("SRC_REPO [REFS...]"); if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error)) goto out; if (!ostree_ensure_repo_writable (repo, error)) goto out; if (argc < 2) { gchar *help = g_option_context_get_help (context, TRUE, NULL); g_printerr ("%s\n", help); g_free (help); g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "DESTINATION must be specified"); goto out; } src_repo_arg = argv[1]; if (src_repo_arg[0] == '/') src_repo_uri = g_strconcat ("file://", src_repo_arg, NULL); else { g_autofree char *cwd = g_get_current_dir (); src_repo_uri = g_strconcat ("file://", cwd, "/", src_repo_arg, NULL); } if (opt_untrusted) pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED; if (opt_bareuseronly_files) pullflags |= OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES; if (opt_disable_fsync) ostree_repo_set_disable_fsync (repo, TRUE); if (argc == 2) { g_autoptr(GFile) src_repo_path = g_file_new_for_path (src_repo_arg); g_autoptr(OstreeRepo) src_repo = ostree_repo_new (src_repo_path); g_autoptr(GHashTable) refs_to_clone = NULL; refs_to_fetch = g_ptr_array_new_with_free_func (g_free); if (!ostree_repo_open (src_repo, cancellable, error)) goto out; /* FIXME: This should grow support for pulling refs from refs/mirrors on * a local repository, using ostree_repo_list_collection_refs(). */ if (!ostree_repo_list_refs (src_repo, NULL, &refs_to_clone, cancellable, error)) goto out; { GHashTableIter hashiter; gpointer hkey, hvalue; g_hash_table_iter_init (&hashiter, refs_to_clone); while (g_hash_table_iter_next (&hashiter, &hkey, &hvalue)) g_ptr_array_add (refs_to_fetch, g_strdup (hkey)); } g_ptr_array_add (refs_to_fetch, NULL); } else { refs_to_fetch = g_ptr_array_new (); for (i = 2; i < argc; i++) { const char *ref = argv[i]; g_ptr_array_add (refs_to_fetch, (char*)ref); } g_ptr_array_add (refs_to_fetch, NULL); } { GVariantBuilder builder; g_autoptr(GVariant) opts = NULL; g_auto(GLnxConsoleRef) console = { 0, }; glnx_console_lock (&console); g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&builder, "{s@v}", "flags", g_variant_new_variant (g_variant_new_int32 (pullflags))); g_variant_builder_add (&builder, "{s@v}", "refs", g_variant_new_variant (g_variant_new_strv ((const char *const*) refs_to_fetch->pdata, -1))); if (opt_remote) g_variant_builder_add (&builder, "{s@v}", "override-remote-name", g_variant_new_variant (g_variant_new_string (opt_remote))); g_variant_builder_add (&builder, "{s@v}", "require-static-deltas", g_variant_new_variant (g_variant_new_boolean (opt_require_static_deltas))); if (opt_gpg_verify) g_variant_builder_add (&builder, "{s@v}", "gpg-verify", g_variant_new_variant (g_variant_new_boolean (TRUE))); if (opt_gpg_verify_summary) g_variant_builder_add (&builder, "{s@v}", "gpg-verify-summary", g_variant_new_variant (g_variant_new_boolean (TRUE))); g_variant_builder_add (&builder, "{s@v}", "depth", g_variant_new_variant (g_variant_new_int32 (opt_depth))); if (console.is_tty) progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console); else progress = ostree_async_progress_new_and_connect (noninteractive_console_progress_changed, &console); opts = g_variant_ref_sink (g_variant_builder_end (&builder)); if (!ostree_repo_pull_with_options (repo, src_repo_uri, opts, progress, cancellable, error)) goto out; if (!console.is_tty) { g_assert (progress); const char *status = ostree_async_progress_get_status (progress); if (status) g_print ("%s\n", status); } ostree_async_progress_finish (progress); } ret = TRUE; out: if (repo) ostree_repo_abort_transaction (repo, cancellable, NULL); return ret; }
int main (int argc, char **argv) { g_autoptr(GOptionContext) option_context = NULL; gboolean ret; gboolean verbose = FALSE; g_autoptr(GError) error = NULL; g_autofree gchar *basename = NULL; g_autofree gchar *icons_dir = NULL; g_autofree gchar *origin = NULL; g_autofree gchar *xml_basename = NULL; g_autofree gchar *output_dir = NULL; g_autofree gchar *prefix = NULL; g_autoptr(AsStore) store = NULL; g_autoptr(GFile) xml_dir = NULL; g_autoptr(GFile) xml_file = NULL; guint min_icon_size = 32; guint i; const GOptionEntry options[] = { { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, /* TRANSLATORS: command line option */ _("Show extra debugging information"), NULL }, { "prefix", '\0', 0, G_OPTION_ARG_FILENAME, &prefix, /* TRANSLATORS: command line option */ _("Set the prefix"), "DIR" }, { "output-dir", '\0', 0, G_OPTION_ARG_FILENAME, &output_dir, /* TRANSLATORS: command line option */ _("Set the output directory"), "DIR" }, { "icons-dir", '\0', 0, G_OPTION_ARG_FILENAME, &icons_dir, /* TRANSLATORS: command line option */ _("Set the icons directory"), "DIR" }, { "origin", '\0', 0, G_OPTION_ARG_STRING, &origin, /* TRANSLATORS: command line option */ _("Set the origin name"), "NAME" }, { "min-icon-size", '\0', 0, G_OPTION_ARG_INT, &min_icon_size, /* TRANSLATORS: command line option */ _("Set the minimum icon size in pixels"), "ICON_SIZE" }, { "basename", '\0', 0, G_OPTION_ARG_STRING, &basename, /* TRANSLATORS: command line option */ _("Set the basenames of the output files"), "NAME" }, { NULL} }; setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); option_context = g_option_context_new (" - APP-IDS"); g_option_context_add_main_entries (option_context, options, NULL); ret = g_option_context_parse (option_context, &argc, &argv, &error); if (!ret) { /* TRANSLATORS: error message */ g_print ("%s: %s\n", _("Failed to parse arguments"), error->message); return EXIT_FAILURE; } if (verbose) g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); /* set defaults */ if (prefix == NULL) prefix = g_strdup ("/usr"); if (output_dir == NULL) output_dir = g_build_filename (prefix, "share/app-info/xmls", NULL); if (icons_dir == NULL) icons_dir = g_build_filename (prefix, "share/app-info/icons", origin, NULL); if (origin == NULL) { g_print ("WARNING: Metadata origin not set, using 'example'\n"); origin = g_strdup ("example"); } if (basename == NULL) basename = g_strdup (origin); if (argc == 1) { g_autofree gchar *tmp = NULL; tmp = g_option_context_get_help (option_context, TRUE, NULL); g_print ("%s", tmp); return EXIT_FAILURE; } store = as_store_new (); as_store_set_api_version (store, 0.8); as_store_set_origin (store, origin); /* load each application specified */ for (i = 1; i < (guint) argc; i++) { const gchar *app_name = argv[i]; g_auto(GStrv) intl_domains = NULL; g_autoptr(AsApp) app_appdata = NULL; g_autoptr(AsApp) app_desktop = NULL; /* TRANSLATORS: we're generating the AppStream data */ g_print ("%s %s\n", _("Processing application"), app_name); app_appdata = load_appdata (prefix, app_name, &error); if (app_appdata == NULL) { /* TRANSLATORS: the .appdata.xml file could not * be loaded */ g_print ("%s: %s\n", _("Error loading AppData file"), error->message); return EXIT_FAILURE; } /* set translations */ if (!as_app_builder_search_translations (app_appdata, prefix, 25, AS_APP_BUILDER_FLAG_NONE, NULL, &error)) { /* TRANSLATORS: the .mo files could not be parsed */ g_print ("%s: %s\n", _("Error parsing translations"), error->message); return EXIT_FAILURE; } /* auto-add kudos */ if (!as_app_builder_search_kudos (app_appdata, prefix, AS_APP_BUILDER_FLAG_NONE, &error)) { /* TRANSLATORS: we could not auto-add the kudo */ g_print ("%s: %s\n", _("Error parsing kudos"), error->message); return EXIT_FAILURE; } /* auto-add provides */ if (!as_app_builder_search_provides (app_appdata, prefix, AS_APP_BUILDER_FLAG_NONE, &error)) { /* TRANSLATORS: we could not auto-add the provides */ g_print ("%s: %s\n", _("Error parsing provides"), error->message); return EXIT_FAILURE; } as_store_add_app (store, app_appdata); app_desktop = load_desktop (prefix, icons_dir, min_icon_size, app_name, as_app_get_id (app_appdata), &error); if (app_desktop == NULL) { /* TRANSLATORS: the .desktop file could not * be loaded */ g_print ("%s: %s\n", _("Error loading desktop file"), error->message); return EXIT_FAILURE; } as_store_add_app (store, app_desktop); } /* create output directory */ if (g_mkdir_with_parents (output_dir, 0755)) { int errsv = errno; g_print ("%s: %s\n", /* TRANSLATORS: this is when the folder could * not be created */ _("Error creating output directory"), strerror (errsv)); return EXIT_FAILURE; } xml_dir = g_file_new_for_path (output_dir); xml_basename = g_strconcat (basename, ".xml.gz", NULL); xml_file = g_file_get_child (xml_dir, xml_basename); /* TRANSLATORS: we've saving the XML file to disk */ g_print ("%s %s\n", _("Saving AppStream"), g_file_get_path (xml_file)); if (!as_store_to_file (store, xml_file, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE | AS_NODE_TO_XML_FLAG_FORMAT_INDENT | AS_NODE_TO_XML_FLAG_ADD_HEADER, NULL, &error)) { /* TRANSLATORS: this is when the destination file * cannot be saved for some reason */ g_print ("%s: %s\n", _("Error saving AppStream file"), error->message); return EXIT_FAILURE; } /* TRANSLATORS: information message */ g_print ("%s\n", _("Done!")); return EXIT_SUCCESS; }
gboolean install_bundle (XdgAppDir *dir, GOptionContext *context, int argc, char **argv, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autoptr(GFile) deploy_base = NULL; g_autoptr(GFile) file = NULL; g_autoptr(GFile) gpg_tmp_file = NULL; const char *filename; g_autofree char *ref = NULL; g_autofree char *origin = NULL; gboolean created_deploy_base = FALSE; gboolean added_remote = FALSE; g_autofree char *to_checksum = NULL; g_auto(GStrv) parts = NULL; g_autoptr(GBytes) gpg_data = NULL; g_autofree char *remote = NULL; OstreeRepo *repo; g_autoptr(OstreeGpgVerifyResult) gpg_result = NULL; g_autoptr(GError) my_error = NULL; g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT; if (argc < 2) return usage_error (context, "bundle filename must be specified", error); filename = argv[1]; repo = xdg_app_dir_get_repo (dir); if (!xdg_app_supports_bundles (repo)) return xdg_app_fail (error, "Your version of ostree is too old to support single-file bundles"); if (!xdg_app_dir_lock (dir, &lock, cancellable, error)) goto out; file = g_file_new_for_commandline_arg (filename); { g_autoptr(GVariant) delta = NULL; g_autoptr(GVariant) metadata = NULL; g_autoptr(GBytes) bytes = NULL; g_autoptr(GVariant) to_csum_v = NULL; g_autoptr(GVariant) gpg_value = NULL; GMappedFile *mfile = g_mapped_file_new (gs_file_get_path_cached (file), FALSE, error); if (mfile == NULL) return FALSE; bytes = g_mapped_file_get_bytes (mfile); g_mapped_file_unref (mfile); delta = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT), bytes, FALSE); g_variant_ref_sink (delta); to_csum_v = g_variant_get_child_value (delta, 3); if (!ostree_validate_structureof_csum_v (to_csum_v, error)) return FALSE; to_checksum = ostree_checksum_from_bytes_v (to_csum_v); metadata = g_variant_get_child_value (delta, 0); if (!g_variant_lookup (metadata, "ref", "s", &ref)) return xdg_app_fail (error, "Invalid bundle, no ref in metadata"); if (!g_variant_lookup (metadata, "origin", "s", &origin)) origin = NULL; gpg_value = g_variant_lookup_value (metadata, "gpg-keys", G_VARIANT_TYPE("ay")); if (gpg_value) { gsize n_elements; const char *data = g_variant_get_fixed_array (gpg_value, &n_elements, 1); gpg_data = g_bytes_new (data, n_elements); } } parts = xdg_app_decompose_ref (ref, error); if (parts == NULL) return FALSE; deploy_base = xdg_app_dir_get_deploy_dir (dir, ref); if (g_file_query_exists (deploy_base, cancellable)) return xdg_app_fail (error, "%s branch %s already installed", parts[1], parts[3]); if (opt_gpg_file != NULL) { /* Override gpg_data from file */ gpg_data = read_gpg_data (cancellable, error); if (gpg_data == NULL) return FALSE; } /* Add a remote for later updates */ if (origin != NULL) { g_auto(GStrv) remotes = ostree_repo_remote_list (repo, NULL); int version = 0; do { g_autofree char *name = NULL; if (version == 0) name = g_strdup_printf ("%s-origin", parts[1]); else name = g_strdup_printf ("%s-%d-origin", parts[1], version); version++; if (remotes == NULL || !g_strv_contains ((const char * const *) remotes, name)) remote = g_steal_pointer (&name); } while (remote == NULL); } if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) return FALSE; ostree_repo_transaction_set_ref (repo, remote, ref, to_checksum); if (!ostree_repo_static_delta_execute_offline (repo, file, FALSE, cancellable, error)) return FALSE; if (gpg_data) { g_autoptr(GFileIOStream) stream; GOutputStream *o; gpg_tmp_file = g_file_new_tmp (".xdg-app-XXXXXX", &stream, error); if (gpg_tmp_file == NULL) return FALSE; o = g_io_stream_get_output_stream (G_IO_STREAM (stream)); if (!g_output_stream_write_all (o, g_bytes_get_data (gpg_data, NULL), g_bytes_get_size (gpg_data), NULL, cancellable, error)) return FALSE; } gpg_result = ostree_repo_verify_commit_ext (repo, to_checksum, NULL, gpg_tmp_file, cancellable, &my_error); if (gpg_tmp_file) g_file_delete (gpg_tmp_file, cancellable, NULL); if (gpg_result == NULL) { /* NOT_FOUND means no gpg signature, we ignore this *if* there * is no gpg key specified in the bundle or by the user */ if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && gpg_data == NULL) g_clear_error (&my_error); else { g_propagate_error (error, g_steal_pointer (&my_error)); return FALSE; } } else { /* If there is no valid gpg signature we fail, unless there is no gpg key specified (on the command line or in the file) because then we trust the source bundle. */ if (ostree_gpg_verify_result_count_valid (gpg_result) == 0 && gpg_data != NULL) return xdg_app_fail (error, "GPG signatures found, but none are in trusted keyring"); } if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error)) return FALSE; if (!g_file_make_directory_with_parents (deploy_base, cancellable, error)) return FALSE; /* From here we need to goto out on error, to clean up */ created_deploy_base = TRUE; if (remote) { g_autoptr(GVariantBuilder) optbuilder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); g_autofree char *basename = g_file_get_basename (file); g_variant_builder_add (optbuilder, "{s@v}", "xa.title", g_variant_new_variant (g_variant_new_string (basename))); g_variant_builder_add (optbuilder, "{s@v}", "xa.noenumerate", g_variant_new_variant (g_variant_new_boolean (TRUE))); g_variant_builder_add (optbuilder, "{s@v}", "xa.prio", g_variant_new_variant (g_variant_new_string ("0"))); if (!ostree_repo_remote_add (repo, remote, origin, g_variant_builder_end (optbuilder), cancellable, error)) goto out; added_remote = TRUE; if (gpg_data) { g_autoptr(GInputStream) gpg_data_as_stream = g_memory_input_stream_new_from_bytes (gpg_data); if (!ostree_repo_remote_gpg_import (repo, remote, gpg_data_as_stream, NULL, NULL, cancellable, error)) goto out; } if (!xdg_app_dir_set_origin (dir, ref, remote, cancellable, error)) goto out; } if (!xdg_app_dir_deploy (dir, ref, to_checksum, cancellable, error)) goto out; if (!xdg_app_dir_make_current_ref (dir, ref, cancellable, error)) goto out; if (strcmp (parts[0], "app") == 0) { if (!xdg_app_dir_update_exports (dir, parts[1], cancellable, error)) goto out; } glnx_release_lock_file (&lock); xdg_app_dir_cleanup_removed (dir, cancellable, NULL); if (!xdg_app_dir_mark_changed (dir, error)) goto out; ret = TRUE; out: if (created_deploy_base && !ret) gs_shutil_rm_rf (deploy_base, cancellable, NULL); if (added_remote && !ret) ostree_repo_remote_delete (repo, remote, NULL, NULL); return ret; }
static gboolean spawn_session (State *state, gboolean run_script, GCancellable *cancellable) { GSubprocessLauncher *launcher = NULL; GSubprocess *subprocess = NULL; GError *error = NULL; gboolean is_running = FALSE; const char *vt; g_debug ("Running X session"); launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); g_subprocess_launcher_setenv (launcher, "DISPLAY", state->display_name, TRUE); g_subprocess_launcher_setenv (launcher, "XAUTHORITY", state->auth_file, TRUE); if (state->environment != NULL) { size_t i; for (i = 0; state->environment[i] != NULL; i++) { g_auto(GStrv) environment_entry = NULL; if (state->environment[i] == '\0') { continue; } environment_entry = g_strsplit (state->environment[i], "=", 2); if (environment_entry[0] == NULL || environment_entry[1] == NULL) { continue; } g_subprocess_launcher_setenv (launcher, environment_entry[0], environment_entry[1], FALSE); } } if (state->bus_address != NULL) { g_subprocess_launcher_setenv (launcher, "DBUS_SESSION_BUS_ADDRESS", state->bus_address, TRUE); } vt = g_getenv ("XDG_VTNR"); if (vt != NULL) { g_subprocess_launcher_setenv (launcher, "WINDOWPATH", vt, TRUE); } if (run_script) { subprocess = g_subprocess_launcher_spawn (launcher, &error, GDMCONFDIR "/Xsession", state->session_command, NULL); } else { int ret; char **argv; ret = g_shell_parse_argv (state->session_command, NULL, &argv, &error); if (!ret) { g_debug ("could not parse session arguments: %s", error->message); goto out; } subprocess = g_subprocess_launcher_spawnv (launcher, (const char * const *) argv, &error); g_strfreev (argv); } if (subprocess == NULL) { g_debug ("could not start session: %s", error->message); goto out; } state->session_subprocess = g_object_ref (subprocess); g_subprocess_wait_async (state->session_subprocess, cancellable, (GAsyncReadyCallback) on_session_finished, state); is_running = TRUE; out: g_clear_object (&subprocess); return is_running; }
gboolean xdg_app_builtin_install (int argc, char **argv, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autoptr(GOptionContext) context = NULL; g_autoptr(XdgAppDir) dir = NULL; g_autoptr(GFile) deploy_base = NULL; const char *repository; const char *name; const char *branch = NULL; g_autofree char *ref = NULL; g_autofree char *installed_ref = NULL; gboolean is_app; gboolean created_deploy_base = FALSE; g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT; g_autoptr(GError) my_error = NULL; context = g_option_context_new ("REPOSITORY NAME [BRANCH] - Install an application or runtime"); if (!xdg_app_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error)) return FALSE; if (opt_bundle) return install_bundle (dir, context, argc, argv, cancellable, error); if (argc < 3) return usage_error (context, "REPOSITORY and NAME must be specified", error); repository = argv[1]; name = argv[2]; if (argc >= 4) branch = argv[3]; if (!opt_app && !opt_runtime) opt_app = opt_runtime = TRUE; installed_ref = xdg_app_dir_find_installed_ref (dir, name, branch, opt_arch, opt_app, opt_runtime, &is_app, &my_error); if (installed_ref != NULL) { return xdg_app_fail (error, "%s %s, branch %s is already installed", is_app ? "App" : "Runtime", name, branch ? branch : "master"); } if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_propagate_error (error, g_steal_pointer (&my_error)); return FALSE; } ref = xdg_app_dir_find_remote_ref (dir, repository, name, branch, opt_arch, opt_app, opt_runtime, &is_app, cancellable, error); if (ref == NULL) return FALSE; deploy_base = xdg_app_dir_get_deploy_dir (dir, ref); if (g_file_query_exists (deploy_base, cancellable)) return xdg_app_fail (error, "Ref %s already deployed", ref); if (!opt_no_pull) { if (!xdg_app_dir_pull (dir, repository, ref, NULL, cancellable, error)) return FALSE; } /* After we create the deploy base we must goto out on errors */ if (!opt_no_deploy) { if (!xdg_app_dir_lock (dir, &lock, cancellable, error)) goto out; if (!g_file_make_directory_with_parents (deploy_base, cancellable, error)) goto out; created_deploy_base = TRUE; if (!xdg_app_dir_set_origin (dir, ref, repository, cancellable, error)) goto out; if (!xdg_app_dir_deploy (dir, ref, NULL, cancellable, error)) goto out; if (is_app) { if (!xdg_app_dir_make_current_ref (dir, ref, cancellable, error)) goto out; if (!xdg_app_dir_update_exports (dir, name, cancellable, error)) goto out; } glnx_release_lock_file (&lock); } xdg_app_dir_cleanup_removed (dir, cancellable, NULL); if (!xdg_app_dir_mark_changed (dir, error)) goto out; ret = TRUE; out: if (created_deploy_base && !ret) gs_shutil_rm_rf (deploy_base, cancellable, NULL); return ret; }
gboolean _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, int bootversion, GPtrArray **out_loader_configs, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; int fd; /* Temporary owned by iterator */ g_autofree char *entries_path = g_strdup_printf ("boot/loader.%d/entries", bootversion); g_autoptr(GPtrArray) ret_loader_configs = NULL; g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; if (!ensure_sysroot_fd (self, error)) goto out; ret_loader_configs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); fd = glnx_opendirat_with_errno (self->sysroot_fd, entries_path, TRUE); if (fd == -1) { if (errno == ENOENT) goto done; else { glnx_set_error_from_errno (error); goto out; } } if (!glnx_dirfd_iterator_init_take_fd (fd, &dfd_iter, error)) goto out; while (TRUE) { struct dirent *dent; struct stat stbuf; if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) goto out; if (dent == NULL) break; if (fstatat (dfd_iter.fd, dent->d_name, &stbuf, 0) != 0) { glnx_set_error_from_errno (error); goto out; } if (g_str_has_prefix (dent->d_name, "ostree-") && g_str_has_suffix (dent->d_name, ".conf") && S_ISREG (stbuf.st_mode)) { glnx_unref_object OstreeBootconfigParser *config = ostree_bootconfig_parser_new (); if (!ostree_bootconfig_parser_parse_at (config, dfd_iter.fd, dent->d_name, cancellable, error)) { g_prefix_error (error, "Parsing %s: ", dent->d_name); goto out; } g_ptr_array_add (ret_loader_configs, g_object_ref (config)); } } /* Callers expect us to give them a sorted array */ g_ptr_array_sort (ret_loader_configs, compare_loader_configs_for_sorting); done: gs_transfer_out_value (out_loader_configs, &ret_loader_configs); ret = TRUE; out: return ret; }
static gboolean enumerate_instances (Column *columns, GError **error) { g_autoptr(GPtrArray) instances = NULL; FlatpakTablePrinter *printer; int i, j; if (columns[0].name == NULL) return TRUE; printer = flatpak_table_printer_new (); flatpak_table_printer_set_columns (printer, columns); instances = flatpak_instance_get_all (); if (instances->len == 0) { /* nothing to show */ return TRUE; } for (j = 0; j < instances->len; j++) { FlatpakInstance *instance = (FlatpakInstance *) g_ptr_array_index (instances, j); flatpak_table_printer_add_column (printer, flatpak_instance_get_id (instance)); for (i = 0; columns[i].name; i++) { if (strcmp (columns[i].name, "pid") == 0) { g_autofree char *pid = g_strdup_printf ("%d", flatpak_instance_get_pid (instance)); flatpak_table_printer_add_column (printer, pid); } else if (strcmp (columns[i].name, "child-pid") == 0) { g_autofree char *pid = g_strdup_printf ("%d", flatpak_instance_get_child_pid (instance)); flatpak_table_printer_add_column (printer, pid); } else if (strcmp (columns[i].name, "application") == 0) flatpak_table_printer_add_column (printer, flatpak_instance_get_app (instance)); else if (strcmp (columns[i].name, "arch") == 0) flatpak_table_printer_add_column (printer, flatpak_instance_get_arch (instance)); else if (strcmp (columns[i].name, "branch") == 0) flatpak_table_printer_add_column (printer, flatpak_instance_get_branch (instance)); else if (strcmp (columns[i].name, "commit") == 0) flatpak_table_printer_add_column_len (printer, flatpak_instance_get_commit (instance), 12); else if (strcmp (columns[i].name, "runtime") == 0) { const char *full_ref = flatpak_instance_get_runtime (instance); if (full_ref != NULL) { g_auto(GStrv) ref = flatpak_decompose_ref (full_ref, NULL); flatpak_table_printer_add_column (printer, ref[1]); } } else if (strcmp (columns[i].name, "runtime-branch") == 0) { const char *full_ref = flatpak_instance_get_runtime (instance); if (full_ref != NULL) { g_auto(GStrv) ref = flatpak_decompose_ref (full_ref, NULL); flatpak_table_printer_add_column (printer, ref[3]); } } else if (strcmp (columns[i].name, "runtime-commit") == 0) flatpak_table_printer_add_column_len (printer, flatpak_instance_get_runtime_commit (instance), 12); } flatpak_table_printer_finish_row (printer); } flatpak_table_printer_print (printer); flatpak_table_printer_free (printer); return TRUE; }