static gboolean dump_runtime (GFile *root, GCancellable *cancellable, GError **error) { int i; g_autoptr(write_archive_t) archive = NULL; g_autoptr(GFile) files = g_file_get_child (root, "files"); archive = archive_write_new (); if (archive == NULL) return xdg_app_fail (error, "Can't allocate archive"); if (archive_write_set_format_gnutar (archive) < ARCHIVE_OK) return xdg_app_fail (error, "Can't set tar format"); if (archive_write_open_FILE (archive, stdout) < ARCHIVE_OK) return xdg_app_fail (error, "can't open stdout"); for (i = 0; i < G_N_ELEMENTS(extra_dirs); i++) { g_autoptr(archive_entry_t) entry = archive_entry_new2 (archive); archive_entry_set_pathname (entry, extra_dirs[i]); archive_entry_set_uid(entry, 0); archive_entry_set_gid(entry, 0); archive_entry_set_perm(entry, 0755); archive_entry_set_mtime(entry, 0, 0); archive_entry_set_filetype (entry, AE_IFDIR); if (archive_write_header (archive, entry) < ARCHIVE_OK) return xdg_app_fail (error, "Can't write tar header"); } for (i = 0; i < G_N_ELEMENTS(extra_symlinks); i++) { g_autoptr(archive_entry_t) entry = NULL; if (g_str_has_prefix (extra_symlinks[i].target, "usr/")) { g_autoptr(GFile) dest = g_file_resolve_relative_path (files, extra_symlinks[i].target + 4); if (!g_file_query_exists (dest, cancellable)) continue; } entry = archive_entry_new2 (archive); archive_entry_set_pathname (entry, extra_symlinks[i].path); archive_entry_set_uid(entry, 0); archive_entry_set_gid(entry, 0); archive_entry_set_perm(entry, 0755); archive_entry_set_mtime(entry, 0, 0); archive_entry_set_filetype (entry, AE_IFLNK); archive_entry_set_symlink (entry, extra_symlinks[i].target); if (archive_write_header (archive, entry) < ARCHIVE_OK) return xdg_app_fail (error, "Can't write tar header"); } if (!dump_files (files, archive, cancellable, "usr", error)) return FALSE; if (archive_write_close (archive) < ARCHIVE_OK) return xdg_app_fail (error, "can't close archive"); return TRUE; }
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_autoptr(GFile) subtree = NULL; g_autofree char *commit = NULL; g_autoptr(GVariant) commit_data = NULL; struct archive *a; OstreeRepoExportArchiveOptions 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 (opt_subpath) subtree = g_file_resolve_relative_path (root, opt_subpath); else subtree = g_object_ref (root); opts.path_prefix = opt_prefix; if (!ostree_repo_export_tree_to_archive (repo, &opts, (OstreeRepoFile*)subtree, 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; }