int
rpmostree_internals_builtin_unpack (int             argc,
                                    char          **argv,
                                    GCancellable   *cancellable,
                                    GError        **error)
{
  int exit_status = EXIT_FAILURE;
  GOptionContext *context = g_option_context_new ("ROOT RPM");
  RpmOstreeUnpackerFlags flags = 0;
  glnx_unref_object RpmOstreeUnpacker *unpacker = NULL;
  const char *rpmpath;
  glnx_fd_close int rootfs_fd = -1;
  
  if (!rpmostree_option_context_parse (context,
                                       option_entries,
                                       &argc, &argv,
                                       RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD,
                                       cancellable,
                                       NULL,
                                       error))
    goto out;

  if (argc < 3)
    {
      rpmostree_usage_error (context, "ROOT and RPM must be specified", error);
      goto out;
    }
  
  if (!glnx_opendirat (AT_FDCWD, argv[1], TRUE, &rootfs_fd, error))
    goto out;

  rpmpath = argv[2];

  /* suid implies owner too...anything else is dangerous, as we might write
   * a setuid binary for the caller.
   */
  if (opt_owner || opt_suid_fcaps)
    flags |= RPMOSTREE_UNPACKER_FLAGS_OWNER;
  if (opt_suid_fcaps)
    flags |= RPMOSTREE_UNPACKER_FLAGS_SUID_FSCAPS;

  unpacker = rpmostree_unpacker_new_at (AT_FDCWD, rpmpath, flags, error);
  if (!unpacker)
    goto out;

  if (!rpmostree_unpacker_unpack_to_dfd (unpacker, rootfs_fd, cancellable, error))
    goto out;

  exit_status = EXIT_SUCCESS;
 out:
  return exit_status;
}
int
rpmostree_internals_builtin_unpack (int             argc,
                                    char          **argv,
                                    GCancellable   *cancellable,
                                    GError        **error)
{
  int exit_status = EXIT_FAILURE;
  GOptionContext *context = g_option_context_new ("ROOT RPM");
  RpmOstreeUnpackerFlags flags = 0;
  glnx_unref_object RpmOstreeUnpacker *unpacker = NULL;
  const char *target;
  const char *rpmpath;
  glnx_fd_close int rootfs_fd = -1;
  glnx_unref_object OstreeRepo *ostree_repo = NULL;
  
  if (!rpmostree_option_context_parse (context,
                                       option_entries,
                                       &argc, &argv,
                                       RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD,
                                       cancellable,
                                       NULL,
                                       error))
    goto out;

  if (argc < 3)
    {
      rpmostree_usage_error (context, "TARGET and RPM must be specified", error);
      goto out;
    }

  target = argv[1];
  rpmpath = argv[2];

  if (opt_to_ostree_repo)
    {
      g_autoptr(GFile) to_ostree_repo_file = g_file_new_for_path (target);

      ostree_repo = ostree_repo_new (to_ostree_repo_file);
      if (!ostree_repo_open (ostree_repo, cancellable, error))
        goto out;
    }
  else
    {
      if (!glnx_opendirat (AT_FDCWD, argv[1], TRUE, &rootfs_fd, error))
        goto out;
    }

  /* suid implies owner too...anything else is dangerous, as we might write
   * a setuid binary for the caller.
   */
  if (opt_owner || opt_suid_fcaps)
    flags |= RPMOSTREE_UNPACKER_FLAGS_OWNER;
  if (opt_suid_fcaps)
    flags |= RPMOSTREE_UNPACKER_FLAGS_SUID_FSCAPS;

  unpacker = rpmostree_unpacker_new_at (AT_FDCWD, rpmpath, flags, error);
  if (!unpacker)
    goto out;

  if (opt_to_ostree_repo)
    {
      const char *branch = rpmostree_unpacker_get_ostree_branch (unpacker);
      g_autofree char *checksum = NULL;

      if (!rpmostree_unpacker_unpack_to_ostree (unpacker, ostree_repo, NULL,
                                                &checksum, cancellable, error))
        goto out;

      g_print ("Imported %s to %s -> %s\n", rpmpath, branch, checksum);
    }
  else
    {
      if (!rpmostree_unpacker_unpack_to_dfd (unpacker, rootfs_fd, cancellable, error))
        goto out;
    }

  exit_status = EXIT_SUCCESS;
 out:
  return exit_status;
}