2014-06-11 21:47:10 +04:00
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
2014-06-12 18:32:21 +04:00
* Copyright ( C ) 2014 Anne LoVerso < anne . loverso @ students . olin . edu >
2014-06-11 21:47:10 +04:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation ; either version 2 of the licence or ( at
* your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place , Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
*/
# include "config.h"
# include <string.h>
# include <glib-unix.h>
# include "rpmostree-builtins.h"
2015-06-13 03:19:16 +03:00
# include "rpmostree-dbus-helpers.h"
2014-06-11 21:47:10 +04:00
2015-06-13 03:19:16 +03:00
# include <libglnx.h>
2014-06-11 21:47:10 +04:00
2014-06-13 21:16:43 +04:00
static gboolean opt_pretty ;
static GOptionEntry option_entries [ ] = {
{ " pretty " , ' p ' , 0 , G_OPTION_ARG_NONE , & opt_pretty , " Display status in formatted rows " , NULL } ,
{ NULL }
} ;
2015-06-13 03:19:16 +03:00
static void
2014-06-13 21:16:43 +04:00
printchar ( char * s , int n )
{
int i ;
for ( i = 0 ; i < n ; i + + )
g_print ( " %s " , s ) ;
g_print ( " \n " ) ;
}
2015-06-13 03:19:16 +03:00
enum {
ID ,
OSNAME ,
SERIAL ,
CHECKSUM ,
VERSION ,
TIMESTAMP ,
ORIGIN ,
SIGNATURES
} ;
2015-04-07 20:49:21 +03:00
2014-06-11 21:47:10 +04:00
gboolean
rpmostree_builtin_status ( int argc ,
2014-06-13 21:16:43 +04:00
char * * argv ,
GCancellable * cancellable ,
GError * * error )
2014-06-11 21:47:10 +04:00
{
gboolean ret = FALSE ;
GOptionContext * context = g_option_context_new ( " - Get the version of the booted system " ) ;
2015-06-13 03:19:16 +03:00
glnx_unref_object RPMOSTreeOS * os_proxy = NULL ;
glnx_unref_object RPMOSTreeSysroot * sysroot_proxy = NULL ;
2015-07-16 21:11:35 +03:00
g_autoptr ( GVariant ) booted_deployment = NULL ;
g_autoptr ( GVariant ) deployments = NULL ;
g_autoptr ( GVariant ) booted_signatures = NULL ;
gchar * booted_id = NULL ; /* borrowed */
2015-06-13 03:19:16 +03:00
2015-07-16 21:11:35 +03:00
const guint CSUM_DISP_LEN = 10 ; /* number of checksum characters to display */
2015-06-13 03:19:16 +03:00
guint i , n ;
2015-07-16 21:11:35 +03:00
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 */
2015-06-13 03:19:16 +03:00
2014-06-13 21:16:43 +04:00
2015-08-05 19:39:07 +03:00
if ( ! rpmostree_option_context_parse ( context ,
option_entries ,
& argc , & argv ,
RPM_OSTREE_BUILTIN_FLAG_NONE ,
cancellable ,
& sysroot_proxy ,
error ) )
2014-06-11 21:47:10 +04:00
goto out ;
2015-08-05 04:09:54 +03:00
if ( ! rpmostree_load_os_proxy ( sysroot_proxy , NULL ,
2015-06-13 03:19:16 +03:00
cancellable , & os_proxy , error ) )
2015-04-07 20:49:21 +03:00
goto out ;
2015-06-13 03:19:16 +03:00
booted_deployment = rpmostree_os_dup_booted_deployment ( os_proxy ) ;
if ( booted_deployment )
{
g_variant_get_child ( booted_deployment , ID , " &s " , & booted_id ) ;
booted_signatures = g_variant_get_child_value ( booted_deployment , SIGNATURES ) ;
}
2014-06-11 21:47:10 +04:00
2015-06-13 03:19:16 +03:00
deployments = rpmostree_sysroot_dup_deployments ( sysroot_proxy ) ;
if ( deployments )
n = g_variant_n_children ( deployments ) ;
else
n = 0 ;
for ( i = 0 ; i < n ; i + + )
2014-06-11 21:47:10 +04:00
{
2015-06-13 03:19:16 +03:00
/* find lengths for use in column output */
if ( ! opt_pretty )
2014-06-12 18:32:21 +04:00
{
2015-07-16 21:11:35 +03:00
g_autoptr ( GVariant ) v = NULL ;
gchar * origin_refspec = NULL ; /* borrowed */
gchar * os_name = NULL ; /* borrowed */
gchar * version_string = NULL ; /* borrowed */
2014-06-13 21:16:43 +04:00
2015-06-13 03:19:16 +03:00
v = g_variant_get_child_value ( deployments , i ) ;
g_variant_get_child ( v , OSNAME , " &s " , & os_name ) ;
g_variant_get_child ( v , VERSION , " &s " , & version_string ) ;
g_variant_get_child ( v , ORIGIN , " &s " , & origin_refspec ) ;
2014-06-13 21:16:43 +04:00
2015-06-13 03:19:16 +03:00
max_osname_len = MAX ( max_osname_len , strlen ( os_name ) ) ;
2014-06-13 21:16:43 +04:00
max_refspec_len = MAX ( max_refspec_len , strlen ( origin_refspec ) ) ;
2015-06-13 03:19:16 +03:00
max_version_len = MAX ( max_version_len , strlen ( version_string ) ) ;
2014-06-12 18:32:21 +04:00
}
2015-06-13 03:19:16 +03:00
}
if ( ! opt_pretty )
{
2014-06-13 21:16:43 +04:00
/* print column headers */
2014-12-12 00:29:12 +03:00
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 " ) ;
2014-06-11 21:47:10 +04:00
}
2014-06-13 21:16:43 +04:00
/* header for "pretty" row output */
else
printchar ( " = " , 60 ) ;
2014-06-12 18:32:21 +04:00
2014-06-13 21:16:43 +04:00
/* print entries for each deployment */
2015-06-13 03:19:16 +03:00
for ( i = 0 ; i < n ; i + + )
2014-06-11 21:47:10 +04:00
{
2014-06-13 21:16:43 +04:00
GDateTime * timestamp = NULL ;
2015-06-13 03:19:16 +03:00
g_autofree char * timestamp_string = NULL ;
g_autofree gchar * truncated_csum = NULL ;
2015-07-16 21:11:35 +03:00
g_autoptr ( GVariant ) v = 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 */
2015-06-13 03:19:16 +03:00
gint64 t ;
gint serial ;
gboolean is_booted = FALSE ;
v = g_variant_get_child_value ( deployments , i ) ;
g_variant_get ( v , " (&s&si&s&st&sav) " ,
& id , & os_name , & serial ,
& checksum , & version_string ,
& t , & origin_refspec , NULL ) ;
signatures = g_variant_get_child_value ( v , SIGNATURES ) ;
is_booted = g_strcmp0 ( booted_id , id ) = = 0 ;
timestamp = g_date_time_new_from_unix_utc ( t ) ;
2014-06-13 21:16:43 +04:00
g_assert ( timestamp ) ;
timestamp_string = g_date_time_format ( timestamp , " %Y-%m-%d %T " ) ;
g_date_time_unref ( timestamp ) ;
/* truncate checksum */
2015-06-13 03:19:16 +03:00
truncated_csum = g_strndup ( checksum , CSUM_DISP_LEN ) ;
2014-06-13 21:16:43 +04:00
/* print deployment info column */
if ( ! opt_pretty )
{
2014-12-12 00:29:12 +03:00
g_print ( " %c %-*s " ,
2015-06-13 03:19:16 +03:00
is_booted ? ' * ' : ' ' ,
2014-12-12 00:29:12 +03:00
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 ,
2015-06-13 03:19:16 +03:00
max_osname_len + buffer , os_name ,
2014-12-12 00:29:12 +03:00
max_refspec_len + buffer , origin_refspec ) ;
2014-06-12 18:32:21 +04:00
}
2014-06-13 21:16:43 +04:00
/* print "pretty" row info */
else
{
2015-06-13 03:19:16 +03:00
guint n_sigs ;
2014-06-13 21:16:43 +04:00
guint tab = 11 ;
char * title = NULL ;
if ( i = = 0 )
title = " DEFAULT ON BOOT " ;
2015-06-13 03:19:16 +03:00
else if ( is_booted | | n < = 2 )
2014-06-13 21:16:43 +04:00
title = " NON-DEFAULT ROLLBACK TARGET " ;
else
title = " NON-DEFAULT DEPLOYMENT " ;
g_print ( " %c %s \n " ,
2015-06-13 03:19:16 +03:00
is_booted ? ' * ' : ' ' ,
2014-06-13 21:16:43 +04:00
title ) ;
printchar ( " - " , 40 ) ;
2014-10-24 10:03:08 +04:00
if ( version_string )
g_print ( " %-*s%-*s \n " , tab , " version " , tab , version_string ) ;
2015-06-13 03:19:16 +03:00
2014-06-13 21:16:43 +04:00
g_print ( " %-*s%-*s \n %-*s%-*s.%d \n %-*s%-*s \n %-*s%-*s \n " ,
tab , " timestamp " , tab , timestamp_string ,
2015-06-13 03:19:16 +03:00
tab , " id " , tab , checksum , serial ,
tab , " osname " , tab , os_name ,
2014-06-13 21:16:43 +04:00
tab , " refspec " , tab , origin_refspec ) ;
2015-04-07 20:49:21 +03:00
2015-06-13 03:19:16 +03:00
n_sigs = g_variant_n_children ( signatures ) ;
if ( n_sigs > 0 )
rpmostree_print_signatures ( signatures , " GPG: " ) ;
2015-04-07 20:49:21 +03:00
2014-06-13 21:16:43 +04:00
printchar ( " = " , 60 ) ;
}
}
2014-06-11 21:47:10 +04:00
2015-04-07 20:49:21 +03:00
/* 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 . */
2015-06-13 03:19:16 +03:00
if ( ! opt_pretty & & booted_signatures ! = NULL )
2015-04-07 20:49:21 +03:00
{
2015-06-13 03:19:16 +03:00
guint n_sigs = g_variant_n_children ( booted_signatures ) ;
if ( n_sigs > 0 )
2015-04-07 20:49:21 +03:00
{
/* XXX If we ever add internationalization, use ngettext() here. */
g_print ( " \n GPG: Found %u signature%s on the booted deployment (*): \n " ,
n_sigs , n_sigs = = 1 ? " " : " s " ) ;
2015-06-13 03:19:16 +03:00
rpmostree_print_signatures ( booted_signatures , " " ) ;
2015-04-07 20:49:21 +03:00
}
}
2014-06-11 21:47:10 +04:00
ret = TRUE ;
2015-06-13 03:19:16 +03:00
out :
2015-08-05 04:09:54 +03:00
/* Does nothing if using the message bus. */
rpmostree_cleanup_peer ( ) ;
2015-06-13 03:19:16 +03:00
return ret ;
2014-06-11 21:47:10 +04:00
}