diff options
author | Colin Walters <walters@verbum.org> | 2016-01-28 14:41:27 -0500 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2016-02-14 09:53:01 -0500 |
commit | 355f8438ef4fe2720d25e8241aa76797b7029522 (patch) | |
tree | 707b54822218cbebd9dbdd37f7900f470613c36d /src/ostree/ot-builtin-export.c | |
parent | e9ccdd2d007801ef25cc7283188942d791889c27 (diff) | |
download | ostree-355f8438ef4fe2720d25e8241aa76797b7029522.tar.gz |
Add an `export` builtin, and API to write to libarchive
At the moment I'm looking at using rpm-ostree to manage RPM inputs
which can then be converted into Docker images. It's most convenient
if we can stream directly out of libostree rather than doing a
checkout + tar combination.
There are also backup/debugging etc. reasons to implement `export` as
well.
Diffstat (limited to 'src/ostree/ot-builtin-export.c')
-rw-r--r-- | src/ostree/ot-builtin-export.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/ostree/ot-builtin-export.c b/src/ostree/ot-builtin-export.c new file mode 100644 index 00000000..2d350b8c --- /dev/null +++ b/src/ostree/ot-builtin-export.c @@ -0,0 +1,148 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2016 Colin Walters <walters@verbum.org> + * + * This library 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 License, 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 "ot-main.h" +#include "ot-builtins.h" +#include "ostree.h" +#include "ostree-repo-file.h" +#include "otutil.h" + +#ifdef HAVE_LIBARCHIVE +#include <archive.h> +#include <archive_entry.h> +#endif + +static char *opt_output_path; +static gboolean opt_no_xattrs; + +static GOptionEntry options[] = { + { "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Skip output of extended attributes", NULL }, + { "output", 'o', 0, G_OPTION_ARG_STRING, &opt_output_path, "Output to PATH ", "PATH" }, + { NULL } +}; + +#ifdef HAVE_LIBARCHIVE + +static void +propagate_libarchive_error (GError **error, + struct archive *a) +{ + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "%s", archive_error_string (a)); +} + +#endif + +gboolean +ostree_builtin_export (int argc, char **argv, GCancellable *cancellable, GError **error) +{ + GOptionContext *context; + glnx_unref_object OstreeRepo *repo = NULL; + gboolean ret = FALSE; + const char *rev; + g_autoptr(GFile) root = NULL; + g_autofree char *commit = NULL; + g_autoptr(GVariant) commit_data = NULL; + struct archive *a; + OstreeRepoArchiveOptions opts = { 0, }; + + context = g_option_context_new ("COMMIT - Stream COMMIT to stdout in tar format"); + + if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error)) + goto out; + +#ifdef HAVE_LIBARCHIVE + + if (argc <= 1) + { + ot_util_usage_error (context, "A COMMIT argument is required", error); + goto out; + } + rev = argv[1]; + + a = archive_write_new (); + /* Yes, this is hardcoded for now. There is + * archive_write_set_format_filter_by_ext() but it's fairly magic. + * Many programs have support now for GNU tar, so should be a good + * default. I also don't want to lock us into everything libarchive + * supports. + */ + if (archive_write_set_format_gnutar (a) != ARCHIVE_OK) + { + propagate_libarchive_error (error, a); + goto out; + } + if (archive_write_add_filter_none (a) != ARCHIVE_OK) + { + propagate_libarchive_error (error, a); + goto out; + } + if (opt_output_path) + { + if (archive_write_open_filename (a, opt_output_path) != ARCHIVE_OK) + { + propagate_libarchive_error (error, a); + goto out; + } + } + else + { + if (archive_write_open_FILE (a, stdout) != ARCHIVE_OK) + { + propagate_libarchive_error (error, a); + goto out; + } + } + + if (opt_no_xattrs) + opts.disable_xattrs = TRUE; + + if (!ostree_repo_read_commit (repo, rev, &root, &commit, cancellable, error)) + goto out; + + if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, commit, &commit_data, error)) + goto out; + + opts.timestamp_secs = ostree_commit_get_timestamp (commit_data); + + if (!ostree_repo_write_tree_to_archive (repo, &opts, (OstreeRepoFile*)root, a, + cancellable, error)) + goto out; + + if (archive_write_close (a) != ARCHIVE_OK) + { + propagate_libarchive_error (error, a); + goto out; + } + +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "This version of ostree is not compiled with libarchive support"); + goto out; +#endif + + ret = TRUE; + out: + if (context) + g_option_context_free (context); + return ret; +} |