コード例 #1
0
gboolean
rpmostree_print_treepkg_diff (OstreeSysroot    *sysroot,
                              GCancellable     *cancellable,
                              GError          **error)
{
  gboolean ret = FALSE;
  OstreeDeployment *booted_deployment;
  OstreeDeployment *new_deployment;
  gs_unref_ptrarray GPtrArray *deployments = 
    ostree_sysroot_get_deployments (sysroot);
  gs_unref_object GFile *booted_root = NULL;
  gs_unref_object GFile *new_root = NULL;

  booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
  
  g_assert (deployments->len > 1);
  new_deployment = deployments->pdata[0];
  
  if (booted_deployment && new_deployment != booted_deployment)
    {
      booted_root = ostree_sysroot_get_deployment_directory (sysroot, booted_deployment);
      new_root = ostree_sysroot_get_deployment_directory (sysroot, new_deployment);
      
      if (!print_rpmdb_diff (booted_root, new_root, cancellable, error))
        goto out;
    }

  ret = TRUE;
 out:
  return ret;
}
コード例 #2
0
OstreeDeployment *
ot_admin_get_indexed_deployment (OstreeSysroot  *sysroot,
                                 int             index,
                                 GError        **error)

{
  g_autoptr(GPtrArray) current_deployments =
    ostree_sysroot_get_deployments (sysroot);

  if (index < 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
                   "Invalid index %d", index);
      return NULL;
    }
  if (index >= current_deployments->len)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
                   "Out of range deployment index %d, expected < %d", index,
                   current_deployments->len);
      return NULL;
    }
  
  return g_object_ref (current_deployments->pdata[index]);
}
コード例 #3
0
gboolean
ot_admin_instutil_builtin_set_kargs (int argc, char **argv, OstreeSysroot *sysroot, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  guint i;
  gs_unref_ptrarray GPtrArray *deployments = NULL;
  OstreeDeployment *first_deployment = NULL;
  gs_unref_ptrarray GPtrArray *new_kargs = NULL;

  if (!ostree_sysroot_load (sysroot, cancellable, error))
    goto out;

  deployments = ostree_sysroot_get_deployments (sysroot);
  if (deployments->len == 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Unable to find a deployment in sysroot");
      goto out;
    }
  first_deployment = deployments->pdata[0];

  new_kargs = g_ptr_array_new ();
  for (i = 1; i < argc; i++)
    g_ptr_array_add (new_kargs, argv[i]);
  g_ptr_array_add (new_kargs, NULL);
  
  if (!ostree_sysroot_deployment_set_kargs (sysroot, first_deployment,
                                            (char**)new_kargs->pdata,
                                            cancellable, error))
    goto out;

  ret = TRUE;
 out:
  return ret;
}
コード例 #4
0
gint
rpmostreed_rollback_deployment_index (const gchar *name,
                                      OstreeSysroot *ot_sysroot,
                                      GError **error)
{
  g_autoptr(GPtrArray) deployments = NULL;
  glnx_unref_object OstreeDeployment *merge_deployment = NULL;

  gint index_to_prepend = -1;
  gint merge_index = -1;
  gint previous_index = -1;
  guint i;

  merge_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name);
  if (merge_deployment == NULL)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "No deployments found for os %s", name);
      goto out;
    }

  deployments = ostree_sysroot_get_deployments (ot_sysroot);
  if (deployments->len < 2)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Found %u deployments, at least 2 required for rollback",
                   deployments->len);
      goto out;
    }

  g_assert (merge_deployment != NULL);
  for (i = 0; i < deployments->len; i++)
    {
      if (deployments->pdata[i] == merge_deployment)
        merge_index = i;

      if (g_strcmp0 (ostree_deployment_get_osname (deployments->pdata[i]), name) == 0 &&
              deployments->pdata[i] != merge_deployment &&
              previous_index < 0)
        {
            previous_index = i;
        }
    }

  g_assert (merge_index < deployments->len);
  g_assert (deployments->pdata[merge_index] == merge_deployment);

  /* If merge deployment is not booted assume we are using it. */
  if (merge_index == 0 && previous_index > 0)
      index_to_prepend = previous_index;
  else
      index_to_prepend = merge_index;

out:
  return index_to_prepend;
}
コード例 #5
0
ファイル: ostree-sysroot.c プロジェクト: resin-io/ostree
/**
 * ostree_sysroot_simple_write_deployment:
 * @sysroot: Sysroot
 * @osname: (allow-none): OS name
 * @new_deployment: Prepend this deployment to the list
 * @merge_deployment: (allow-none): Use this deployment for configuration merge
 * @flags: Flags controlling behavior
 * @cancellable: Cancellable
 * @error: Error
 *
 * Prepend @new_deployment to the list of deployments, commit, and
 * cleanup.  By default, all other deployments for the given @osname
 * except the merge deployment and the booted deployment will be
 * garbage collected.
 *
 * If %OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN is
 * specified, then all current deployments will be kept.
 */
gboolean
ostree_sysroot_simple_write_deployment (OstreeSysroot      *sysroot,
                                        const char         *osname,
                                        OstreeDeployment   *new_deployment,
                                        OstreeDeployment   *merge_deployment,
                                        OstreeSysrootSimpleWriteDeploymentFlags flags,
                                        GCancellable       *cancellable,
                                        GError            **error)
{
  gboolean ret = FALSE;
  guint i;
  OstreeDeployment *booted_deployment = NULL;
  g_autoptr(GPtrArray) deployments = NULL;
  g_autoptr(GPtrArray) new_deployments = g_ptr_array_new_with_free_func (g_object_unref);
  gboolean retain = (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN) > 0;

  deployments = ostree_sysroot_get_deployments (sysroot);
  booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);

  if (osname == NULL && booted_deployment)
    osname = ostree_deployment_get_osname (booted_deployment);

  g_ptr_array_add (new_deployments, g_object_ref (new_deployment));

  for (i = 0; i < deployments->len; i++)
    {
      OstreeDeployment *deployment = deployments->pdata[i];
      
      /* Keep deployments with different osnames, as well as the
       * booted and merge deployments
       */
      if (retain ||
          (osname != NULL &&
           strcmp (ostree_deployment_get_osname (deployment), osname) != 0) ||
          ostree_deployment_equal (deployment, booted_deployment) ||
          ostree_deployment_equal (deployment, merge_deployment))
        {
          g_ptr_array_add (new_deployments, g_object_ref (deployment));
        }
    }

  if (!ostree_sysroot_write_deployments (sysroot, new_deployments, cancellable, error))
    goto out;

  if (!ostree_sysroot_cleanup (sysroot, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  return ret;
}
コード例 #6
0
OstreeDeployment *
rpmostreed_deployment_get_for_id (OstreeSysroot *sysroot,
                                  const gchar *deploy_id)
{
  g_autoptr(GPtrArray) deployments = NULL;
  guint i;

  OstreeDeployment *deployment = NULL;

  deployments = ostree_sysroot_get_deployments (sysroot);
  if (deployments == NULL)
    goto out;

  for (i=0; i<deployments->len; i++)
    {
      g_autofree gchar *id = rpmostreed_deployment_generate_id (deployments->pdata[i]);
      if (g_strcmp0 (deploy_id, id) == 0) {
        deployment = g_object_ref (deployments->pdata[i]);
      }
    }

out:
  return deployment;
}
コード例 #7
0
gboolean
ot_admin_builtin_status (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
  const int is_tty = isatty (1);
  const char *red_bold_prefix = is_tty ? "\x1b[31m\x1b[1m" : "";
  const char *red_bold_suffix = is_tty ? "\x1b[22m\x1b[0m" : "";

  g_autoptr(GOptionContext) context = g_option_context_new ("");

  g_autoptr(OstreeSysroot) sysroot = NULL;
  if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
                                          OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED,
                                          invocation, &sysroot, cancellable, error))
    return FALSE;

  g_autoptr(OstreeRepo) repo = NULL;
  if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
    return FALSE;

  g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot);
  OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);

  g_autoptr(OstreeDeployment) pending_deployment = NULL;
  g_autoptr(OstreeDeployment) rollback_deployment = NULL;
  if (booted_deployment)
    ostree_sysroot_query_deployments_for (sysroot, NULL, &pending_deployment,
                                          &rollback_deployment);

  if (deployments->len == 0)
    {
      g_print ("No deployments.\n");
    }
  else
    {
      for (guint i = 0; i < deployments->len; i++)
        {
          OstreeDeployment *deployment = deployments->pdata[i];
          const char *ref = ostree_deployment_get_csum (deployment);

          /* Load the backing commit; shouldn't normally fail, but if it does,
           * we stumble on.
           */
          g_autoptr(GVariant) commit = NULL;
          (void)ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, ref,
                                          &commit, NULL);
          g_autoptr(GVariant) commit_metadata = NULL;
          if (commit)
            commit_metadata = g_variant_get_child_value (commit, 0);

          const char *version = NULL;
          const char *source_title = NULL;
          if (commit_metadata)
            {
              (void) g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_VERSION, "&s", &version);
              (void) g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_SOURCE_TITLE, "&s", &source_title);
            }

          GKeyFile *origin = ostree_deployment_get_origin (deployment);

          const char *deployment_status = "";
          if (deployment == pending_deployment)
            deployment_status = " (pending)";
          else if (deployment == rollback_deployment)
            deployment_status = " (rollback)";
          g_print ("%c %s %s.%d%s\n",
                   deployment == booted_deployment ? '*' : ' ',
                   ostree_deployment_get_osname (deployment),
                   ostree_deployment_get_csum (deployment),
                   ostree_deployment_get_deployserial (deployment),
                   deployment_status);
          if (version)
            g_print ("    Version: %s\n", version);

          OstreeDeploymentUnlockedState unlocked = ostree_deployment_get_unlocked (deployment);
          switch (unlocked)
            {
            case OSTREE_DEPLOYMENT_UNLOCKED_NONE:
              break;
            default:
              g_print ("    %sUnlocked: %s%s\n", red_bold_prefix,
                       ostree_deployment_unlocked_state_to_string (unlocked),
                       red_bold_suffix);
            }
          if (!origin)
            g_print ("    origin: none\n");
          else
            {
              g_autofree char *origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
              if (!origin_refspec)
                g_print ("    origin: <unknown origin type>\n");
              else
                g_print ("    origin refspec: %s\n", origin_refspec);
              if (source_title)
                g_print ("    `- %s\n", source_title);
            }

          if (deployment_get_gpg_verify (deployment, repo))
            {
              g_autoptr(GString) output_buffer = g_string_sized_new (256);
              /* Print any digital signatures on this commit. */

              g_autoptr(GError) local_error = NULL;
              g_autoptr(OstreeGpgVerifyResult) result =
                ostree_repo_verify_commit_ext (repo, ref, NULL, NULL,
                                               cancellable, &local_error);

              /* G_IO_ERROR_NOT_FOUND just means the commit is not signed. */
              if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
                {
                  g_clear_error (&local_error);
                  continue;
                }
              else if (local_error != NULL)
                {
                  g_propagate_error (error, g_steal_pointer (&local_error));
                  return FALSE;
                }

              const guint n_signatures = ostree_gpg_verify_result_count_all (result);
              for (guint jj = 0; jj < n_signatures; jj++)
                {
                  ostree_gpg_verify_result_describe (result, jj, output_buffer, "    GPG: ",
                                                     OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT);
                }

              g_print ("%s", output_buffer->str);
            }
        }
    }

  return TRUE;
}
コード例 #8
0
static gboolean
sysroot_populate_deployments_unlocked (RpmostreedSysroot *self,
				       gboolean *out_changed,
				       GError **error)
{
  gboolean ret = FALSE;
  OstreeDeployment *booted = NULL; /* owned by sysroot */
  g_autofree gchar *booted_id = NULL;
  g_autoptr(GPtrArray) deployments = NULL;
  g_autoptr(GHashTable) seen_osnames = NULL;
  GHashTableIter iter;
  gpointer hashkey;
  gpointer value;
  GVariantBuilder builder;
  guint i;
  gboolean sysroot_changed;
  gboolean repo_changed;
  struct stat repo_new_stat;

  if (!ostree_sysroot_load_if_changed (self->ot_sysroot, &sysroot_changed, self->cancellable, error))
    goto out;

  if (fstat (ostree_repo_get_dfd (self->repo), &repo_new_stat) < 0)
    {
      glnx_set_error_from_errno (error);
      goto out;
    }

  repo_changed = !(self->repo_last_stat.st_mtim.tv_sec == repo_new_stat.st_mtim.tv_sec
		   && self->repo_last_stat.st_mtim.tv_nsec == repo_new_stat.st_mtim.tv_nsec);
  if (repo_changed)
    self->repo_last_stat = repo_new_stat;

  if (!(sysroot_changed || repo_changed))
    {
      ret = TRUE;
      if (out_changed)
	*out_changed = FALSE;
      goto out;
    }

  g_debug ("loading deployments");
  g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));

  seen_osnames = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);

  /* Updated booted property */
  booted = ostree_sysroot_get_booted_deployment (self->ot_sysroot);
  if (booted)
    {
      const gchar *os = ostree_deployment_get_osname (booted);
      g_autofree gchar *path = rpmostreed_generate_object_path (BASE_DBUS_PATH,
                                                                os, NULL);
      rpmostree_sysroot_set_booted (RPMOSTREE_SYSROOT (self), path);
      booted_id = rpmostreed_deployment_generate_id (booted);
    }
  else
    {
      rpmostree_sysroot_set_booted (RPMOSTREE_SYSROOT (self), "/");
    }

  /* Add deployment interfaces */
  deployments = ostree_sysroot_get_deployments (self->ot_sysroot);

  for (i = 0; deployments != NULL && i < deployments->len; i++)
    {
      GVariant *variant;
      OstreeDeployment *deployment = deployments->pdata[i];
      const char *deployment_os;
      
      variant = rpmostreed_deployment_generate_variant (deployment, booted_id, self->repo, error);
      if (!variant)
	goto out;
      g_variant_builder_add_value (&builder, variant);

      deployment_os = ostree_deployment_get_osname (deployment);

      /* Have we not seen this osname instance before?  If so, add it
       * now.
       */
      if (!g_hash_table_contains (self->os_interfaces, deployment_os))
	{
	  RPMOSTreeOS *obj = rpmostreed_os_new (self->ot_sysroot, self->repo,
						deployment_os,
                                                self->transaction_monitor);
          g_hash_table_insert (self->os_interfaces, g_strdup (deployment_os), obj);
	}
      /* Owned by deployment, hash lifetime is smaller */
      g_hash_table_add (seen_osnames, (char*)deployment_os);
    }

  /* Remove dead os paths */
  g_hash_table_iter_init (&iter, self->os_interfaces);
  while (g_hash_table_iter_next (&iter, &hashkey, &value))
    {
      if (!g_hash_table_contains (seen_osnames, hashkey))
        {
          g_object_run_dispose (G_OBJECT (value));
          g_hash_table_iter_remove (&iter);
        }
    }

  rpmostree_sysroot_set_deployments (RPMOSTREE_SYSROOT (self),
                                     g_variant_builder_end (&builder));
  g_debug ("finished deployments");

  ret = TRUE;
  if (out_changed)
    *out_changed = TRUE;
 out:
  return ret;
}
コード例 #9
0
gboolean
ostree_admin_option_context_parse (GOptionContext *context,
                                   const GOptionEntry *main_entries,
                                   int *argc,
                                   char ***argv,
                                   OstreeAdminBuiltinFlags flags,
                                   OstreeSysroot **out_sysroot,
                                   GCancellable *cancellable,
                                   GError **error)
{
  g_autoptr(GFile) sysroot_path = NULL;
  glnx_unref_object OstreeSysroot *sysroot = NULL;
  gboolean success = FALSE;

  /* Entries are listed in --help output in the order added.  We add the
   * main entries ourselves so that we can add the --sysroot entry first. */

  g_option_context_add_main_entries (context, global_admin_entries, NULL);

  if (!ostree_option_context_parse (context, main_entries, argc, argv, OSTREE_BUILTIN_FLAG_NO_REPO, NULL, cancellable, error))
    goto out;

  if (opt_sysroot != NULL)
    sysroot_path = g_file_new_for_path (opt_sysroot);

  sysroot = ostree_sysroot_new (sysroot_path);

  if (flags & OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER)
    {
      GFile *path = ostree_sysroot_get_path (sysroot);

      /* If sysroot path is "/" then user must be root. */
      if (!g_file_has_parent (path, NULL) && getuid () != 0)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
                       "You must be root to perform this command");
          goto out;
        }
    }

  if (opt_print_current_dir)
    {
      g_autoptr(GPtrArray) deployments = NULL;
      OstreeDeployment *first_deployment;
      g_autoptr(GFile) deployment_file = NULL;
      g_autofree char *deployment_path = NULL;

      if (!ostree_sysroot_load (sysroot, cancellable, error))
        goto out;

      deployments = ostree_sysroot_get_deployments (sysroot);
      if (deployments->len == 0)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Unable to find a deployment in sysroot");
          goto out;
        }
      first_deployment = deployments->pdata[0];
      deployment_file = ostree_sysroot_get_deployment_directory (sysroot, first_deployment);
      deployment_path = g_file_get_path (deployment_file);

      g_print ("%s\n", deployment_path);

      /* The g_autoptr, g_autofree etc. don't happen when we explicitly
       * exit, making valgrind complain about leaks */
      g_clear_object (&sysroot);
      g_clear_object (&sysroot_path);
      g_clear_object (&deployment_file);
      g_clear_pointer (&deployments, g_ptr_array_unref);
      g_clear_pointer (&deployment_path, g_free);
      exit (EXIT_SUCCESS);
    }

  if ((flags & OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED) == 0)
    {
      /* Released when sysroot is finalized, or on process exit */
      if (!ot_admin_sysroot_lock (sysroot, error))
        goto out;
    }

  if (out_sysroot)
    *out_sysroot = g_steal_pointer (&sysroot);

  success = TRUE;

out:
  return success;
}
gboolean
ot_admin_instutil_builtin_selinux_ensure_labeled (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  const char *policy_name;
  g_autoptr(GFile) subpath = NULL;
  const char *prefix = NULL;
  glnx_unref_object OstreeSePolicy *sepolicy = NULL;
  g_autoptr(GPtrArray) deployments = NULL;
  OstreeDeployment *first_deployment;
  GOptionContext *context = NULL;
  glnx_unref_object OstreeSysroot *sysroot = NULL;
  g_autoptr(GFile) deployment_path = NULL;

  context = g_option_context_new ("[SUBPATH PREFIX] - relabel all or part of a deployment");

  if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
                                          OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER | OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED,
                                          &sysroot, cancellable, error))
    goto out;

  if (!ostree_sysroot_load (sysroot, cancellable, error))
    goto out;

  deployments = ostree_sysroot_get_deployments (sysroot);
  if (deployments->len == 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Unable to find a deployment in sysroot");
      goto out;
    }
  first_deployment = deployments->pdata[0];
  deployment_path = ostree_sysroot_get_deployment_directory (sysroot, first_deployment);

  if (argc >= 2)
    {
      subpath = g_file_new_for_path (argv[1]);
      prefix = argv[2];
    }
  else
    {
      subpath = g_object_ref (deployment_path);
      prefix = "";
    }

  sepolicy = ostree_sepolicy_new (deployment_path, cancellable, error);
  if (!sepolicy)
    goto out;
  
  policy_name = ostree_sepolicy_get_name (sepolicy);
  if (policy_name)
    {
      g_print ("Relabeling using policy '%s'\n", policy_name);
      if (!selinux_relabel_dir (sepolicy, subpath, prefix,
                                cancellable, error))
        goto out;
    }
  else
    g_print ("No SELinux policy found in deployment '%s'\n",
             gs_file_get_path_cached (deployment_path));

  ret = TRUE;
 out:
  if (context)
    g_option_context_free (context);
  return ret;
}
コード例 #11
0
gboolean
ot_admin_builtin_undeploy (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  GOptionContext *context;
  gs_unref_object OstreeSysroot *sysroot = NULL;
  const char *deploy_index_str;
  int deploy_index;
  gs_unref_ptrarray GPtrArray *current_deployments = NULL;
  gs_unref_object OstreeDeployment *booted_deployment = NULL;
  gs_unref_object OstreeDeployment *target_deployment = NULL;

  context = g_option_context_new ("INDEX - Delete deployment INDEX");

  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, "INDEX must be specified", error);
      goto out;
    }

  if (!ostree_sysroot_load (sysroot, cancellable, error))
    goto out;
  current_deployments = ostree_sysroot_get_deployments (sysroot);

  deploy_index_str = argv[1];
  deploy_index = atoi (deploy_index_str);

  target_deployment = ot_admin_get_indexed_deployment (sysroot, deploy_index, error);
  if (!target_deployment)
    goto out;

  if (target_deployment == ostree_sysroot_get_booted_deployment (sysroot))
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
                   "Cannot undeploy currently booted deployment %i", deploy_index);
      goto out;
    }
  
  g_ptr_array_remove_index (current_deployments, deploy_index);

  if (!ostree_sysroot_write_deployments (sysroot, current_deployments,
                                         cancellable, error))
    goto out;

  g_print ("Deleted deployment %s.%d\n", ostree_deployment_get_csum (target_deployment),
           ostree_deployment_get_deployserial (target_deployment));
  
  if (!ostree_sysroot_cleanup (sysroot, cancellable, error))
    {
      g_prefix_error (error, "Performing final cleanup: ");
      goto out;
    }

  ret = TRUE;
 out:
  if (context)
    g_option_context_free (context);
  return ret;
}
コード例 #12
0
gboolean
ot_admin_instutil_builtin_set_kargs (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  guint i;
  g_autoptr(GPtrArray) deployments = NULL;
  OstreeDeployment *first_deployment = NULL;
  GOptionContext *context = NULL;
  glnx_unref_object OstreeSysroot *sysroot = NULL;
  __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL;

  context = g_option_context_new ("ARGS - set new kernel command line arguments");

  if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
                                          OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER | OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED,
                                          &sysroot, cancellable, error))
    goto out;

  if (!ostree_sysroot_load (sysroot, cancellable, error))
    goto out;

  deployments = ostree_sysroot_get_deployments (sysroot);
  if (deployments->len == 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Unable to find a deployment in sysroot");
      goto out;
    }
  first_deployment = deployments->pdata[0];

  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_proc_cmdline)
    {
      if (!_ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error))
        goto out;
    }
  else if (opt_merge)
    {
      OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (first_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_replace)
    {
      _ostree_kernel_args_replace_argv (kargs, opt_replace);
    }

  if (opt_append)
    {
      _ostree_kernel_args_append_argv (kargs, opt_append);
    }

  for (i = 1; i < argc; i++)
    _ostree_kernel_args_append (kargs, argv[i]);

  {
    g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs);

    if (!ostree_sysroot_deployment_set_kargs (sysroot, first_deployment,
                                              kargs_strv,
                                              cancellable, error))
      goto out;
  }

  ret = TRUE;
 out:
  if (context)
    g_option_context_free (context);
  return ret;
}
コード例 #13
0
gboolean
rpmostree_builtin_rollback (int             argc,
                            char          **argv,
                            GCancellable   *cancellable,
                            GError        **error)
{
  gboolean ret = FALSE;
  GOptionContext *context = g_option_context_new ("- Revert to the previously booted tree");
  gs_unref_object GFile *sysroot_path = NULL;
  gs_unref_object OstreeSysroot *sysroot = NULL;
  gs_free char *origin_description = NULL;
  gs_unref_ptrarray GPtrArray *deployments = NULL;
  gs_unref_ptrarray GPtrArray *new_deployments =
    g_ptr_array_new_with_free_func (g_object_unref);
  OstreeDeployment *booted_deployment = NULL;
  guint i;
  guint booted_index;
  guint index_to_prepend;
  
  if (!rpmostree_option_context_parse (context, option_entries, &argc, &argv, error))
    goto out;

  sysroot_path = g_file_new_for_path (opt_sysroot);
  sysroot = ostree_sysroot_new (sysroot_path);
  if (!ostree_sysroot_load (sysroot, cancellable, error))
    goto out;

  booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
  if (booted_deployment == NULL)
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "Not currently booted into an OSTree system");
      goto out;
    }

  deployments = ostree_sysroot_get_deployments (sysroot);
  if (deployments->len < 2)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Found %u deployments, at least 2 required for rollback",
                   deployments->len);
      goto out;
    }

  g_assert (booted_deployment != NULL);
  for (booted_index = 0; booted_index < deployments->len; booted_index++)
    {
      if (deployments->pdata[booted_index] == booted_deployment)
        break;
    }
  g_assert (booted_index < deployments->len);
  g_assert (deployments->pdata[booted_index] == booted_deployment);
  
  if (booted_index != 0)
    {
      /* There is an earlier deployment, let's assume we want to just
       * insert the current one in front.
       */

       /*
       What this does is, if we're NOT in the default boot index, it plans to prepend
       our current index (1, since we can't have more than two trees) so that it becomes index 0 
       (default) and the current default becomes index 1
       */
      index_to_prepend = booted_index;
    }
  else
    {
      /* We're booted into the first, let's roll back to the previous */
      index_to_prepend = 1;
    }
  
  g_ptr_array_add (new_deployments, g_object_ref (deployments->pdata[index_to_prepend]));
  for (i = 0; i < deployments->len; i++)
    {
      if (i == index_to_prepend)
        continue;
      g_ptr_array_add (new_deployments, g_object_ref (deployments->pdata[i]));
    }

  g_print ("Moving '%s.%d' to be first deployment\n",
           ostree_deployment_get_csum (deployments->pdata[index_to_prepend]),
           ostree_deployment_get_deployserial (deployments->pdata[index_to_prepend]));

  if (!ostree_sysroot_write_deployments (sysroot, new_deployments, cancellable,
                                         error))
    goto out;

  if (opt_reboot)
    gs_subprocess_simple_run_sync (NULL, GS_SUBPROCESS_STREAM_DISPOSITION_INHERIT,
                                   cancellable, error,
                                   "systemctl", "reboot", NULL);
  else
    {
      if (!rpmostree_print_treepkg_diff (sysroot, cancellable, error))
        goto out;

      g_print ("Successfully reset deployment order; run \"systemctl reboot\" to start a reboot\n");
    }

  if (opt_reboot)
  ret = TRUE;
 out:
  return ret;
}
コード例 #14
0
gboolean
ot_admin_builtin_status (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  g_autoptr(GOptionContext) context = NULL;
  glnx_unref_object OstreeSysroot *sysroot = NULL;
  gboolean ret = FALSE;
  glnx_unref_object OstreeRepo *repo = NULL;
  OstreeDeployment *booted_deployment = NULL;
  g_autoptr(GPtrArray) deployments = NULL;
  const int is_tty = isatty (1);
  const char *red_bold_prefix = is_tty ? "\x1b[31m\x1b[1m" : "";
  const char *red_bold_suffix = is_tty ? "\x1b[22m\x1b[0m" : "";
  guint i;

  context = g_option_context_new ("List deployments");

  if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
                                          OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED,
                                          &sysroot, cancellable, error))
    goto out;

  if (!ostree_sysroot_load (sysroot, cancellable, error))
    goto out;

  if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
    goto out;

  deployments = ostree_sysroot_get_deployments (sysroot);
  booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);

  if (deployments->len == 0)
    {
      g_print ("No deployments.\n");
    }
  else
    {
      for (i = 0; i < deployments->len; i++)
        {
          OstreeDeployment *deployment = deployments->pdata[i];
          GKeyFile *origin;
          const char *ref = ostree_deployment_get_csum (deployment);
          OstreeDeploymentUnlockedState unlocked = ostree_deployment_get_unlocked (deployment);
          g_autofree char *version = version_of_commit (repo, ref);
          glnx_unref_object OstreeGpgVerifyResult *result = NULL;
          GString *output_buffer;
          guint jj, n_signatures;
          GError *local_error = NULL;

          origin = ostree_deployment_get_origin (deployment);

          g_print ("%c %s %s.%d\n",
                   deployment == booted_deployment ? '*' : ' ',
                   ostree_deployment_get_osname (deployment),
                   ostree_deployment_get_csum (deployment),
                   ostree_deployment_get_deployserial (deployment));
          if (version)
            g_print ("    Version: %s\n", version);
          switch (unlocked)
            {
            case OSTREE_DEPLOYMENT_UNLOCKED_NONE:
              break;
            default:
              g_print ("    %sUnlocked: %s%s\n", red_bold_prefix,
                       ostree_deployment_unlocked_state_to_string (unlocked),
                       red_bold_suffix);
            }
          if (!origin)
            g_print ("    origin: none\n");
          else
            {
              g_autofree char *origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
              if (!origin_refspec)
                g_print ("    origin: <unknown origin type>\n");
              else
                g_print ("    origin refspec: %s\n", origin_refspec);
            }

          if (deployment_get_gpg_verify (deployment, repo))
            {
              /* Print any digital signatures on this commit. */

              result = ostree_repo_verify_commit_ext (repo, ref, NULL, NULL,
                                                      cancellable, &local_error);

              /* G_IO_ERROR_NOT_FOUND just means the commit is not signed. */
              if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
                {
                  g_clear_error (&local_error);
                  continue;
                }
              else if (local_error != NULL)
                {
                  g_propagate_error (error, local_error);
                  goto out;
                }

              output_buffer = g_string_sized_new (256);
              n_signatures = ostree_gpg_verify_result_count_all (result);

              for (jj = 0; jj < n_signatures; jj++)
                {
                  ostree_gpg_verify_result_describe (result, jj, output_buffer, "    GPG: ",
                                                     OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT);
                }

              g_print ("%s", output_buffer->str);
              g_string_free (output_buffer, TRUE);
            }
        }
    }

  ret = TRUE;
 out:
  return ret;
}