static void command_line (GApplication *app, GApplicationCommandLine *cmdline) { GVariantDict *options; const gchar *name = NULL; gint autoquit = 0; Demo *d, *c; GDoDemoFunc func = 0; GtkWidget *window, *demo; activate (app); options = g_application_command_line_get_options_dict (cmdline); g_variant_dict_lookup (options, "run", "&s", &name); g_variant_dict_lookup (options, "autoquit", "i", &autoquit); if (name == NULL) goto out; window = gtk_application_get_windows (GTK_APPLICATION (app))->data; d = gtk_demos; while (d->title) { c = d->children; if (g_strcmp0 (d->name, name) == 0) { func = d->func; goto out; } d++; while (c && c->title) { if (g_strcmp0 (c->name, name) == 0) { func = c->func; goto out; } c++; } } out: if (func) { demo = (func) (window); gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window)); gtk_window_set_modal (GTK_WINDOW (demo), TRUE); } if (autoquit > 0) g_timeout_add_seconds (autoquit, auto_quit, app); }
static RpmOstreeTransactionLiveFsFlags livefs_flags_from_options (GVariant *options) { RpmOstreeTransactionLiveFsFlags ret = 0; GVariantDict options_dict; gboolean opt = FALSE; g_variant_dict_init (&options_dict, options); if (g_variant_dict_lookup (&options_dict, "dry-run", "b", &opt) && opt) ret |= RPMOSTREE_TRANSACTION_LIVEFS_FLAG_DRY_RUN; if (g_variant_dict_lookup (&options_dict, "replace", "b", &opt) && opt) ret |= RPMOSTREE_TRANSACTION_LIVEFS_FLAG_REPLACE; g_variant_dict_clear (&options_dict); return ret; }
static void gbp_greeter_application_addin_handle_command_line (IdeApplicationAddin *addin, IdeApplication *application, GApplicationCommandLine *cmdline) { GbpGreeterApplicationAddin *self = (GbpGreeterApplicationAddin *)addin; g_auto(GStrv) argv = NULL; GVariantDict *dict; const gchar *clone_uri = NULL; gint argc; g_assert (GBP_IS_GREETER_APPLICATION_ADDIN (self)); g_assert (IDE_IS_APPLICATION (application)); g_assert (G_IS_APPLICATION_COMMAND_LINE (cmdline)); dict = g_application_command_line_get_options_dict (cmdline); argv = ide_application_get_argv (IDE_APPLICATION (application), cmdline); argc = g_strv_length (argv); /* * If we are processing the arguments for the startup of the primary * instance, then we want to show the greeter if no arguments are * provided. (That means argc == 1, the programe executable). * * Also, if they provided --greeter or -g we'll show a new greeter. */ if ((!g_application_command_line_get_is_remote (cmdline) && argc == 1) || g_variant_dict_contains (dict, "greeter")) { present_greeter_with_surface (NULL, NULL, addin); return; } /* * If the --clone=URI option was provided, switch the greeter to the * clone surface and begin cloning. */ if (dict != NULL && g_variant_dict_lookup (dict, "clone", "&s", &clone_uri)) { IdeGreeterWorkspace *workspace; IdeWorkbench *workbench; IdeSurface *surface; workbench = ide_workbench_new (); ide_application_add_workbench (self->application, workbench); workspace = ide_greeter_workspace_new (self->application); ide_workbench_add_workspace (workbench, IDE_WORKSPACE (workspace)); surface = ide_workspace_get_surface_by_name (IDE_WORKSPACE (workspace), "clone"); ide_workspace_set_visible_surface (IDE_WORKSPACE (workspace), surface); if (IDE_IS_CLONE_SURFACE (surface)) ide_clone_surface_set_uri (IDE_CLONE_SURFACE (surface), clone_uri); ide_workbench_focus_workspace (workbench, IDE_WORKSPACE (workspace)); } }
static gint photos_thumbnailer_handle_local_options (GApplication *application, GVariantDict *options) { PhotosThumbnailer *self = PHOTOS_THUMBNAILER (application); gint ret_val = EXIT_FAILURE; if (g_variant_dict_lookup (options, "address", "s", &self->address)) ret_val = -1; return ret_val; }
static int local_options (GApplication *app, GVariantDict *options, gpointer data) { gboolean version = FALSE; g_variant_dict_lookup (options, "version", "b", &version); if (version) { print_version (); return 0; } return -1; }
gboolean rpmostree_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; GOptionContext *context = g_option_context_new ("- Perform a system upgrade"); glnx_unref_object RPMOSTreeOS *os_proxy = NULL; glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL; g_autoptr(GVariant) default_deployment = NULL; g_autofree char *transaction_address = NULL; if (!rpmostree_option_context_parse (context, option_entries, &argc, &argv, RPM_OSTREE_BUILTIN_FLAG_NONE, cancellable, &sysroot_proxy, error)) goto out; if (opt_check_diff && opt_reboot) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "cannot specify both --reboot and --check-diff"); goto out; } if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname, cancellable, &os_proxy, error)) goto out; if (opt_check_diff) { if (!rpmostree_os_call_download_update_rpm_diff_sync (os_proxy, &transaction_address, cancellable, error)) goto out; } else { g_signal_connect (os_proxy, "notify::default-deployment", G_CALLBACK (default_changed_callback), &default_deployment); if (!rpmostree_os_call_upgrade_sync (os_proxy, get_args_variant (), &transaction_address, cancellable, error)) goto out; } if (!rpmostree_transaction_get_response_sync (sysroot_proxy, transaction_address, cancellable, error)) goto out; if (opt_check_diff) { /* yes, doing this without using dbus */ gs_unref_object OstreeSysroot *sysroot = NULL; gs_unref_object OstreeRepo *repo = NULL; gs_unref_object GFile *rpmdbdir = NULL; gs_unref_object GFile *sysroot_file = NULL; g_autofree char *origin_description = NULL; g_autoptr(GVariant) cached_update = NULL; const char *sysroot_path; GVariantDict upgrade_dict; _cleanup_rpmrev_ struct RpmRevisionData *rpmrev1 = NULL; _cleanup_rpmrev_ struct RpmRevisionData *rpmrev2 = NULL; gs_free char *ref = NULL; /* location of this rev */ gs_free char *remote = NULL; if (!rpmostree_os_get_has_cached_update_rpm_diff (os_proxy)) goto out; sysroot_path = rpmostree_sysroot_get_path (sysroot_proxy); sysroot_file = g_file_new_for_path (sysroot_path); sysroot = ostree_sysroot_new (sysroot_file); if (!ostree_sysroot_load (sysroot, cancellable, error)) goto out; if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) goto out; cached_update = rpmostree_os_dup_cached_update(os_proxy); g_variant_dict_init (&upgrade_dict, cached_update); if (!g_variant_dict_lookup (&upgrade_dict, "origin", "s", &origin_description)) goto out; if (!ostree_parse_refspec (origin_description, &remote, &ref, error)) goto out; if (rpmReadConfigFiles (NULL, NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "rpm failed to init: %s", rpmlogMessage ()); goto out; } if (!(rpmrev1 = rpmrev_new (repo, ostree_deployment_get_csum (ostree_sysroot_get_booted_deployment (sysroot)), NULL, cancellable, error))) goto out; if (!(rpmrev2 = rpmrev_new (repo, ref, NULL, cancellable, error))) goto out; rpmhdrs_diff_prnt_diff (rpmhdrs_diff (rpmrev_get_headers (rpmrev1), rpmrev_get_headers (rpmrev2))); } else { /* nothing changed */ if (default_deployment == NULL) { goto out; } if (!opt_reboot) { const char *sysroot_path; sysroot_path = rpmostree_sysroot_get_path (sysroot_proxy); if (!rpmostree_print_treepkg_diff_from_sysroot_path (sysroot_path, cancellable, error)) goto out; g_print ("Run \"systemctl reboot\" to start a reboot\n"); } } ret = TRUE; out: /* Does nothing if using the message bus. */ rpmostree_cleanup_peer (); return ret; }
static gint gedit_app_command_line (GApplication *application, GApplicationCommandLine *cl) { GeditAppPrivate *priv; GVariantDict *options; const gchar *encoding_charset; const gchar **remaining_args; priv = gedit_app_get_instance_private (GEDIT_APP (application)); options = g_application_command_line_get_options_dict (cl); g_variant_dict_lookup (options, "new-window", "b", &priv->new_window); g_variant_dict_lookup (options, "new-document", "b", &priv->new_document); g_variant_dict_lookup (options, "geometry", "s", &priv->geometry); if (g_variant_dict_contains (options, "wait")) { priv->command_line = cl; } if (g_variant_dict_lookup (options, "encoding", "&s", &encoding_charset)) { priv->encoding = gtk_source_encoding_get_from_charset (encoding_charset); if (priv->encoding == NULL) { g_application_command_line_printerr (cl, _("%s: invalid encoding."), encoding_charset); } } /* Parse filenames */ if (g_variant_dict_lookup (options, G_OPTION_REMAINING, "^a&ay", &remaining_args)) { gint i; for (i = 0; remaining_args[i]; i++) { if (*remaining_args[i] == '+') { if (*(remaining_args[i] + 1) == '\0') { /* goto the last line of the document */ priv->line_position = G_MAXINT; priv->column_position = 0; } else { get_line_column_position (remaining_args[i] + 1, &priv->line_position, &priv->column_position); } } else if (*remaining_args[i] == '-' && *(remaining_args[i] + 1) == '\0') { priv->stdin_stream = g_application_command_line_get_stdin (cl); } else { GFile *file; file = g_application_command_line_create_file_for_arg (cl, remaining_args[i]); priv->file_list = g_slist_prepend (priv->file_list, file); } } priv->file_list = g_slist_reverse (priv->file_list); g_free (remaining_args); } g_application_activate (application); clear_options (GEDIT_APP (application)); return 0; }
OstreeDeltaEndianness _ostree_delta_get_endianness (GVariant *superblock, gboolean *out_was_heuristic) { guint8 endianness_char; g_autoptr(GVariant) delta_meta = NULL; g_autoptr(GVariantDict) delta_metadict = NULL; guint64 total_size = 0; guint64 total_usize = 0; guint total_objects = 0; delta_meta = g_variant_get_child_value (superblock, 0); delta_metadict = g_variant_dict_new (delta_meta); if (out_was_heuristic) *out_was_heuristic = FALSE; if (g_variant_dict_lookup (delta_metadict, "ostree.endianness", "y", &endianness_char)) { switch (endianness_char) { case 'l': return OSTREE_DELTA_ENDIAN_LITTLE; case 'B': return OSTREE_DELTA_ENDIAN_BIG; default: return OSTREE_DELTA_ENDIAN_INVALID; } } if (out_was_heuristic) *out_was_heuristic = TRUE; { g_autoptr(GVariant) meta_entries = NULL; guint n_parts; guint i; gboolean is_byteswapped = FALSE; g_variant_get_child (superblock, 6, "@a" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT, &meta_entries); n_parts = g_variant_n_children (meta_entries); for (i = 0; i < n_parts; i++) { g_autoptr(GVariant) objects = NULL; guint64 size, usize; guint n_objects; g_variant_get_child (meta_entries, i, "(u@aytt@ay)", NULL, NULL, &size, &usize, &objects); n_objects = (guint)(g_variant_get_size (objects) / OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN); total_objects += n_objects; total_size += size; total_usize += usize; if (size > usize) { double ratio = ((double)size)/((double)usize); /* This should really never happen where compressing things makes it more than 50% bigger. */ if (ratio > 1.2) { is_byteswapped = TRUE; break; } } } if (!is_byteswapped) { /* If the average object size is greater than 4GiB, let's assume * we're dealing with opposite endianness. I'm fairly confident * no one is going to be shipping peta- or exa- byte size ostree * deltas, period. Past the gigabyte scale you really want * bittorrent or something. */ if ((total_size / total_objects) > G_MAXUINT32) { is_byteswapped = TRUE; } } if (is_byteswapped) { switch (G_BYTE_ORDER) { case G_BIG_ENDIAN: return OSTREE_DELTA_ENDIAN_LITTLE; case G_LITTLE_ENDIAN: return OSTREE_DELTA_ENDIAN_BIG; default: g_assert_not_reached (); } } return OSTREE_DELTA_ENDIAN_INVALID; } }
static GtkWidget* create_new_window (GtkApplication *application, GVariantDict *options) { dg_lmem gchar* command = NULL; dg_lmem gchar* title = NULL; gboolean opt_show_title; gboolean opt_update_title; gboolean opt_no_headerbar; g_object_get (dwt_settings_get_instance (), "show-title", &opt_show_title, "update-title", &opt_update_title, "no-header-bar", &opt_no_headerbar, "command", &command, "title", &title, NULL); const gchar *opt_command = command; const gchar *opt_title = title; const gchar *opt_workdir = NULL; if (options) { gboolean opt_no_auto_title = FALSE; g_variant_dict_lookup (options, "title-on-maximize", "b", &opt_show_title); g_variant_dict_lookup (options, "no-header-bar", "b", &opt_no_headerbar); g_variant_dict_lookup (options, "no-auto-title", "b", &opt_no_auto_title); g_variant_dict_lookup (options, "workdir", "&s", &opt_workdir); g_variant_dict_lookup (options, "command", "&s", &opt_command); g_variant_dict_lookup (options, "title", "&s", &opt_title); if (opt_no_auto_title) opt_update_title = FALSE; } if (!opt_workdir) opt_workdir = g_get_home_dir (); if (!opt_command) opt_command = guess_shell (); /* * Title either comes from the default value of the "title" setting, * or from the command line flag, but should never be NULL at this * point. */ g_assert (opt_title); dg_lerr GError *gerror = NULL; gint command_argv_len = 0; gchar **command_argv = NULL; if (!g_shell_parse_argv (opt_command, &command_argv_len, &command_argv, &gerror)) { g_printerr ("%s: coult not parse command: %s\n", __func__, gerror->message); return NULL; } GtkWidget *window = gtk_application_window_new (application); gtk_widget_set_visual (window, gdk_screen_get_system_visual (gtk_widget_get_screen (window))); gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (window), FALSE); gtk_window_set_title (GTK_WINDOW (window), opt_title); gtk_window_set_hide_titlebar_when_maximized (GTK_WINDOW (window), !opt_show_title); g_action_map_add_action_entries (G_ACTION_MAP (window), win_actions, G_N_ELEMENTS (win_actions), window); VteTerminal *vtterm = VTE_TERMINAL (vte_terminal_new ()); configure_term_widget (vtterm, options); term_char_size_changed (vtterm, vte_terminal_get_char_width (vtterm), vte_terminal_get_char_height (vtterm), window); g_signal_connect (G_OBJECT (window), "notify::has-toplevel-focus", G_CALLBACK (window_has_toplevel_focus_notified), vtterm); g_signal_connect (G_OBJECT (vtterm), "char-size-changed", G_CALLBACK (term_char_size_changed), window); g_signal_connect (G_OBJECT (vtterm), "child-exited", G_CALLBACK (term_child_exited), window); g_signal_connect (G_OBJECT (vtterm), "bell", G_CALLBACK (term_beeped), window); g_signal_connect (G_OBJECT (vtterm), "button-release-event", G_CALLBACK (term_mouse_button_released), setup_popover (vtterm)); /* * Propagate title changes to the window. */ if (opt_update_title) g_object_bind_property (G_OBJECT (vtterm), "window-title", G_OBJECT (window), "title", G_BINDING_DEFAULT); if (!opt_no_headerbar) setup_header_bar (window, vtterm, opt_show_title); gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (vtterm)); gtk_widget_set_receives_default (GTK_WIDGET (vtterm), TRUE); /* We need to realize and show the window for it to have a valid XID */ gtk_widget_show_all (window); gchar **command_env = g_get_environ (); #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_SCREEN (gtk_widget_get_screen (window))) { GdkWindow *gdk_window = gtk_widget_get_window (window); if (gdk_window) { gchar window_id[NDIGITS10(unsigned long)]; snprintf (window_id, sizeof (window_id), "%lu", GDK_WINDOW_XID (gdk_window)); command_env = g_environ_setenv (command_env, "WINDOWID", window_id, TRUE); } else { g_printerr ("No window, cannot set $WINDOWID!\n"); } }
static void configure_term_widget (VteTerminal *vtterm, GVariantDict *options) { /* Pick default settings from the settings... */ dg_lmem gchar *opt_font = NULL; dg_lmem gchar *opt_theme = NULL; dg_lmem gchar *opt_fgcolor = NULL; dg_lmem gchar *opt_bgcolor = NULL; gboolean opt_bold; guint opt_scroll; DwtSettings *settings = dwt_settings_get_instance (); g_object_get (settings, "font", &opt_font, "theme", &opt_theme, "allow-bold", &opt_bold, "scrollback", &opt_scroll, "foreground-color", &opt_fgcolor, "background-color", &opt_bgcolor, NULL); /* * This ensures that properties are updated for the terminal whenever they * change in the configuration files. * * TODO: For now this is done only for those properties which cannot be * overriden using command line flags. */ static const struct { const gchar *setting_name; const gchar *property_name; GBindingFlags bind_flags; } property_bind_map[] = { { "mouse-autohide", "pointer-autohide", G_BINDING_SYNC_CREATE }, { "audible-bell", "audible-bell", G_BINDING_SYNC_CREATE }, }; for (guint i = 0; i < G_N_ELEMENTS (property_bind_map); i++) { g_object_bind_property (settings, property_bind_map[i].setting_name, G_OBJECT (vtterm), property_bind_map[i].property_name, property_bind_map[i].bind_flags); } /* ...and allow command line options to override them. */ if (options) { dg_lmem gchar *cmd_font = NULL; g_variant_dict_lookup (options, "font", "s", &cmd_font); if (cmd_font) SWAP (gchar*, cmd_font, opt_font); dg_lmem gchar *cmd_theme = NULL; g_variant_dict_lookup (options, "theme", "s", &cmd_theme); if (cmd_theme) SWAP (gchar*, cmd_theme, opt_theme); g_variant_dict_lookup (options, "allow-bold", "b", &opt_bold); g_variant_dict_lookup (options, "scrollback", "u", &opt_scroll); } PangoFontDescription *fontd = pango_font_description_from_string (opt_font); if (fontd) { if (!pango_font_description_get_family (fontd)) pango_font_description_set_family_static (fontd, "monospace"); if (!pango_font_description_get_size (fontd)) pango_font_description_set_size (fontd, 12 * PANGO_SCALE); vte_terminal_set_font (vtterm, fontd); pango_font_description_free (fontd); fontd = NULL; } const Theme *theme = &themes[1]; if (opt_theme) { theme = find_theme (opt_theme); if (!theme) { g_printerr ("No such theme '%s', using default (linux)\n", opt_theme); theme = &themes[1]; } } GdkRGBA fgcolor, bgcolor; if (!(opt_fgcolor && gdk_rgba_parse (&fgcolor, opt_fgcolor))) fgcolor = theme->fg; if (!(opt_bgcolor && gdk_rgba_parse (&bgcolor, opt_bgcolor))) bgcolor = theme->bg; vte_terminal_set_rewrap_on_resize (vtterm, TRUE); vte_terminal_set_scroll_on_keystroke (vtterm, TRUE); vte_terminal_set_audible_bell (vtterm, FALSE); vte_terminal_set_scroll_on_output (vtterm, FALSE); vte_terminal_set_allow_bold (vtterm, opt_bold); vte_terminal_set_scrollback_lines (vtterm, opt_scroll); vte_terminal_set_cursor_blink_mode (vtterm, VTE_CURSOR_BLINK_OFF); vte_terminal_set_cursor_shape (vtterm, VTE_CURSOR_SHAPE_BLOCK); vte_terminal_set_colors (vtterm, &fgcolor, &bgcolor, theme->colors, G_N_ELEMENTS (theme->colors)); const GRegexCompileFlags regex_compile_flags = G_REGEX_CASELESS | G_REGEX_OPTIMIZE | G_REGEX_MULTILINE; gint match_tag = vte_terminal_match_add_gregex (vtterm, g_regex_new (uri_regexp, regex_compile_flags, G_REGEX_MATCH_NOTEMPTY, NULL), G_REGEX_MATCH_NOTEMPTY); vte_terminal_match_set_cursor_type (vtterm, match_tag, GDK_HAND2); }
int rpmostree_builtin_initramfs (int argc, char **argv, RpmOstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = g_option_context_new ("- Enable or disable local initramfs regeneration"); _cleanup_peer_ GPid peer_pid = 0; glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL; if (!rpmostree_option_context_parse (context, option_entries, &argc, &argv, invocation, cancellable, NULL, NULL, &sysroot_proxy, &peer_pid, error)) return EXIT_FAILURE; glnx_unref_object RPMOSTreeOS *os_proxy = NULL; if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname, cancellable, &os_proxy, error)) return EXIT_FAILURE; if (!(opt_enable || opt_disable)) { GVariantIter iter; g_autoptr(GVariant) deployments = rpmostree_sysroot_dup_deployments (sysroot_proxy); if (opt_reboot) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "--reboot must be used with --enable or --disable"); return EXIT_FAILURE; } g_variant_iter_init (&iter, deployments); while (TRUE) { gboolean cur_regenerate; g_autoptr(GVariant) child = g_variant_iter_next_value (&iter); g_autoptr(GVariantDict) dict = NULL; g_autofree char **initramfs_args = NULL; gboolean is_booted; if (child == NULL) break; dict = g_variant_dict_new (child); if (!g_variant_dict_lookup (dict, "booted", "b", &is_booted)) continue; if (!is_booted) continue; if (!g_variant_dict_lookup (dict, "regenerate-initramfs", "b", &cur_regenerate)) cur_regenerate = FALSE; if (cur_regenerate) { g_variant_dict_lookup (dict, "initramfs-args", "^a&s", &initramfs_args); } g_print ("Initramfs regeneration: %s\n", cur_regenerate ? "enabled" : "disabled"); if (initramfs_args) { g_print ("Initramfs args: "); for (char **iter = initramfs_args; iter && *iter; iter++) g_print ("%s ", *iter); g_print ("\n"); } } } else if (opt_enable && opt_disable) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Cannot simultaenously specify --enable and --disable"); return EXIT_FAILURE; } else { char *empty_strv[] = {NULL}; if (opt_disable && opt_add_arg) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Cannot simultaenously specify --disable and --arg"); return EXIT_FAILURE; } if (!opt_add_arg) opt_add_arg = empty_strv; g_autofree char *transaction_address = NULL; if (!rpmostree_os_call_set_initramfs_state_sync (os_proxy, opt_enable, (const char *const*)opt_add_arg, get_args_variant (), &transaction_address, cancellable, error)) return EXIT_FAILURE; if (!rpmostree_transaction_get_response_sync (sysroot_proxy, transaction_address, cancellable, error)) return EXIT_FAILURE; g_print ("Initramfs regeneration is now: %s\n", opt_enable ? "enabled" : "disabled"); } return EXIT_SUCCESS; }
int rpmostree_builtin_status (int argc, char **argv, GCancellable *cancellable, GError **error) { int exit_status = EXIT_FAILURE; GOptionContext *context = g_option_context_new ("- Get the version of the booted system"); glnx_unref_object RPMOSTreeOS *os_proxy = NULL; glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL; g_autoptr(GVariant) booted_deployment = NULL; g_autoptr(GVariant) deployments = NULL; g_autoptr(GVariant) booted_signatures = NULL; g_autoptr(GPtrArray) deployment_dicts = NULL; GVariantIter iter; GVariant *child; g_autofree gchar *booted_id = NULL; const guint CSUM_DISP_LEN = 10; /* number of checksum characters to display */ guint i, n; guint max_timestamp_len = 19; /* length of timestamp "YYYY-MM-DD HH:MM:SS" */ guint max_id_len = CSUM_DISP_LEN; /* length of checksum ID */ guint max_osname_len = 0; /* maximum length of osname - determined in code */ guint max_refspec_len = 0; /* maximum length of refspec - determined in code */ guint max_version_len = 0; /* maximum length of version - determined in code */ guint buffer = 5; /* minimum space between end of one entry and new column */ if (!rpmostree_option_context_parse (context, option_entries, &argc, &argv, RPM_OSTREE_BUILTIN_FLAG_NONE, cancellable, &sysroot_proxy, error)) goto out; if (!rpmostree_load_os_proxy (sysroot_proxy, NULL, cancellable, &os_proxy, error)) goto out; booted_deployment = rpmostree_os_dup_booted_deployment (os_proxy); if (booted_deployment) { GVariantDict dict; g_variant_dict_init (&dict, booted_deployment); g_variant_dict_lookup (&dict, "id", "s", &booted_id); booted_signatures = g_variant_dict_lookup_value (&dict, "signatures", G_VARIANT_TYPE ("av")); g_variant_dict_clear (&dict); } deployment_dicts = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_dict_unref); deployments = rpmostree_sysroot_dup_deployments (sysroot_proxy); g_variant_iter_init (&iter, deployments); while ((child = g_variant_iter_next_value (&iter)) != NULL) { GVariantDict *dict = g_variant_dict_new (child); /* Takes ownership of the dictionary */ g_ptr_array_add (deployment_dicts, dict); /* find lengths for use in column output */ if (!opt_pretty) { gchar *origin_refspec = NULL; /* borrowed */ gchar *os_name = NULL; /* borrowed */ gchar *version_string = NULL; /* borrowed */ /* osname should always be present. */ if (g_variant_dict_lookup (dict, "osname", "&s", &os_name)) max_osname_len = MAX (max_osname_len, strlen (os_name)); else { const char *id = NULL; g_variant_dict_lookup (dict, "id", "&s", &id); g_critical ("Deployment '%s' missing osname", id != NULL ? id : "?"); } if (g_variant_dict_lookup (dict, "version", "&s", &version_string)) max_version_len = MAX (max_version_len, strlen (version_string)); if (g_variant_dict_lookup (dict, "origin", "&s", &origin_refspec)) max_refspec_len = MAX (max_refspec_len, strlen (origin_refspec)); } g_variant_unref (child); } if (!opt_pretty) { /* print column headers */ g_print (" %-*s", max_timestamp_len+buffer,"TIMESTAMP (UTC)"); if (max_version_len) g_print ("%-*s", max_version_len+buffer,"VERSION"); g_print ("%-*s%-*s%-*s\n", max_id_len+buffer, "ID", max_osname_len+buffer, "OSNAME", max_refspec_len+buffer, "REFSPEC"); } /* header for "pretty" row output */ else printchar ("=", 60); n = deployment_dicts->len; /* print entries for each deployment */ for (i = 0; i < n; i++) { GVariantDict *dict; g_autoptr(GDateTime) timestamp = NULL; g_autofree char *timestamp_string = NULL; g_autofree gchar *truncated_csum = NULL; g_autoptr(GVariant) signatures = NULL; gchar *id = NULL; /* borrowed */ gchar *origin_refspec = NULL; /* borrowed */ gchar *os_name = NULL; /* borrowed */ gchar *version_string = NULL; /* borrowed */ gchar *checksum = NULL; /* borrowed */ guint64 t = 0; gint serial; gboolean is_booted = FALSE; dict = g_ptr_array_index (deployment_dicts, i); g_variant_dict_lookup (dict, "id", "&s", &id); g_variant_dict_lookup (dict, "osname", "&s", &os_name); g_variant_dict_lookup (dict, "serial", "i", &serial); g_variant_dict_lookup (dict, "checksum", "s", &checksum); g_variant_dict_lookup (dict, "version", "s", &version_string); g_variant_dict_lookup (dict, "timestamp", "t", &t); g_variant_dict_lookup (dict, "origin", "s", &origin_refspec); signatures = g_variant_dict_lookup_value (dict, "signatures", G_VARIANT_TYPE ("av")); is_booted = g_strcmp0 (booted_id, id) == 0; timestamp = g_date_time_new_from_unix_utc (t); if (timestamp != NULL) timestamp_string = g_date_time_format (timestamp, "%Y-%m-%d %T"); else timestamp_string = g_strdup_printf ("(invalid)"); /* truncate checksum */ truncated_csum = g_strndup (checksum, CSUM_DISP_LEN); /* print deployment info column */ if (!opt_pretty) { g_print ("%c %-*s", is_booted ? '*' : ' ', max_timestamp_len+buffer, timestamp_string); if (max_version_len) g_print ("%-*s", max_version_len+buffer, version_string ? version_string : ""); g_print ("%-*s%-*s%-*s\n", max_id_len+buffer, truncated_csum, max_osname_len+buffer, os_name, max_refspec_len+buffer, origin_refspec); } /* print "pretty" row info */ else { guint tab = 11; char *title = NULL; if (i==0) title = "DEFAULT ON BOOT"; else if (is_booted || n <= 2) title = "NON-DEFAULT ROLLBACK TARGET"; else title = "NON-DEFAULT DEPLOYMENT"; g_print (" %c %s\n", is_booted ? '*' : ' ', title); printchar ("-", 40); if (version_string) g_print (" %-*s%-*s\n", tab, "version", tab, version_string); g_print (" %-*s%-*s\n %-*s%-*s.%d\n %-*s%-*s\n %-*s%-*s\n", tab, "timestamp", tab, timestamp_string, tab, "id", tab, checksum, serial, tab, "osname", tab, os_name, tab, "refspec", tab, origin_refspec); if (signatures != NULL) rpmostree_print_signatures (signatures, " GPG: "); printchar ("=", 60); } } /* Print any signatures for the booted deployment, but only in NON-pretty * mode. We save this for the end to preserve the tabular formatting for * deployments. */ if (!opt_pretty && booted_signatures != NULL) { guint n_sigs = g_variant_n_children (booted_signatures); if (n_sigs > 0) { /* XXX If we ever add internationalization, use ngettext() here. */ g_print ("\nGPG: Found %u signature%s on the booted deployment (*):\n", n_sigs, n_sigs == 1 ? "" : "s"); rpmostree_print_signatures (booted_signatures, " "); } } exit_status = EXIT_SUCCESS; out: /* Does nothing if using the message bus. */ rpmostree_cleanup_peer (); return exit_status; }