Imported Upstream version 2016.6

This commit is contained in:
Simon McVittie committed 2016-06-26 12:12:26 +01:00
1 parent a7b5654e44
commit 24762929e2
115 files changed
+4857 -2074

No files matched your search

+21 -5
View File
@@ -323,11 +323,6 @@ global:
ostree_deployment_unlocked_state_to_string;
} LIBOSTREE_2016.3;
/* NOTE NOTE NOTE
* Versions above here are released. Only add symbols below this line.
* NOTE NOTE NOTE
*/
LIBOSTREE_2016.5 {
global:
ostree_repo_import_object_from_with_trust;
@@ -337,3 +332,24 @@ global:
ostree_repo_get_remote_boolean_option;
ostree_repo_set_cache_dir;
} LIBOSTREE_2016.4;
LIBOSTREE_2016.6 {
global:
ostree_gpg_verify_result_require_valid_signature;
ostree_raw_file_to_archive_z2_stream;
ostree_repo_gpg_verify_data;
ostree_repo_remote_fetch_summary_with_options;
} LIBOSTREE_2016.5;
/* NOTE NOTE NOTE
* Versions above here are released. Only add symbols below this line.
* NOTE NOTE NOTE
*/
/* Uncomment this when adding a new symbol */
/*
LIBOSTREE_2016.7 {
global:
ostree_some_new_symbol;
} LIBOSTREE_2016.6;
*/
+1 -1
View File
@@ -23,7 +23,7 @@
#include "ostree-async-progress.h"
/**
* SECTION:libostree-async-progress
* SECTION:ostree-async-progress
* @title: Progress notification system for asynchronous operations
* @short_description: Values representing progress
*
+68
View File
@@ -0,0 +1,68 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2016 Endless Mobile, Inc.
*
* 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.
*
* Author: Krzesimir Nowak <krzesimir@kinvolk.io>
*/
#pragma once
#include <ostree.h>
G_BEGIN_DECLS
#ifndef OSTREE_WITH_AUTOCLEANUPS
#define OSTREE_WITH_AUTOCLEANUPS 0
#endif
/* ostree can use g_autoptr backports from libglnx when glib is too
* old, but still avoid exposing them to users that also have an old
* glib */
#if defined(OSTREE_COMPILATION) || (OSTREE_WITH_AUTOCLEANUPS && GLIB_CHECK_VERSION(2, 44, 0))
/*
* The following types have no specific clear/free/unref functions, so
* they can be used as the stack-allocated variables or as the
* g_autofree heap-allocated variables.
*
* OstreeRepoTransactionStats
* OstreeRepoImportArchiveOptions
* OstreeRepoExportArchiveOptions
* OstreeRepoCheckoutOptions
*/
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeDiffItem, ostree_diff_item_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoCommitModifier, ostree_repo_commit_modifier_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoDevInoCache, ostree_repo_devino_cache_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeAsyncProgress, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeBootconfigParser, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeDeployment, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeGpgVerifyResult, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMutableTree, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepo, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFile, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeSePolicy, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeSysroot, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeSysrootUpgrader, g_object_unref)
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (OstreeRepoCommitTraverseIter, ostree_repo_commit_traverse_iter_clear)
#endif
G_END_DECLS
+2 -1
View File
@@ -138,7 +138,8 @@ _ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader,
bootversion);
/* This should follow the symbolic link to the current bootversion. */
config_contents = gs_file_load_contents_utf8 (self->config_path, cancellable, error);
config_contents = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (self->config_path), NULL,
cancellable, error);
if (!config_contents)
goto out;
+2 -1
View File
@@ -113,7 +113,8 @@ _ostree_bootloader_uboot_write_config (OstreeBootloader *bootloader,
g_autoptr(GPtrArray) new_lines = NULL;
/* This should follow the symbolic link to the current bootversion. */
config_contents = gs_file_load_contents_utf8 (self->config_path, cancellable, error);
config_contents = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (self->config_path), NULL,
cancellable, error);
if (!config_contents)
return FALSE;
+2 -3
View File
@@ -83,7 +83,7 @@ _ostree_make_temporary_symlink_at (int tmp_dirfd,
GFileInfo * _ostree_header_gfile_info_new (mode_t mode, uid_t uid, gid_t gid);
/* XX + / + checksum-2 + . + extension, but let's just use 256 for a
/* XX/checksum-2.extension, but let's just use 256 for a
* bit of overkill.
*/
#define _OSTREE_LOOSE_PATH_MAX (256)
@@ -112,8 +112,7 @@ _ostree_get_relative_static_delta_part_path (const char *from,
const char *to,
guint i);
static inline char *
_ostree_get_commitpartial_path (const char *checksum)
static inline char * _ostree_get_commitpartial_path (const char *checksum)
{
return g_strconcat ("state/", checksum, ".commitpartial", NULL);
}
+106 -39
View File
@@ -26,11 +26,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <gio/gfiledescriptorbased.h>
#include "libglnx.h"
#include "ostree.h"
#include "ostree-core-private.h"
#include "ostree-chain-input-stream.h"
#include "otutil.h"
#include "libglnx.h"
#define ALIGN_VALUE(this, boundary) \
(( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
@@ -47,7 +47,7 @@ zlib_file_header_parse (GVariant *metadata,
GError **error);
/**
* SECTION:libostree-core
* SECTION:ostree-core
* @title: Core repository-independent functions
* @short_description: Create, validate, and convert core data types
*
@@ -400,6 +400,98 @@ write_file_header_update_checksum (GOutputStream *out,
return ret;
}
/*
* header_and_input_to_stream:
* @file_header: A file header
* @input: File raw content stream
* @out_input: (out): Serialized object stream
* @out_header_size: (out): Length of the header
* @cancellable: Cancellable
* @error: Error
*
* Combines @file_header and @input into a single stream.
*/
static gboolean
header_and_input_to_stream (GVariant *file_header,
GInputStream *input,
GInputStream **out_input,
guint64 *out_header_size,
GCancellable *cancellable,
GError **error)
{
gpointer header_data;
gsize header_size;
g_autoptr(GInputStream) ret_input = NULL;
g_autoptr(GPtrArray) streams = NULL;
g_autoptr(GOutputStream) header_out_stream = NULL;
g_autoptr(GInputStream) header_in_stream = NULL;
header_out_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
if (!_ostree_write_variant_with_size (header_out_stream, file_header, 0, NULL, NULL,
cancellable, error))
return FALSE;
if (!g_output_stream_close (header_out_stream, cancellable, error))
return FALSE;
header_size = g_memory_output_stream_get_data_size ((GMemoryOutputStream*) header_out_stream);
header_data = g_memory_output_stream_steal_data ((GMemoryOutputStream*) header_out_stream);
header_in_stream = g_memory_input_stream_new_from_data (header_data, header_size, g_free);
streams = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
g_ptr_array_add (streams, g_object_ref (header_in_stream));
if (input)
g_ptr_array_add (streams, g_object_ref (input));
ret_input = (GInputStream*)ostree_chain_input_stream_new (streams);
ot_transfer_out_value (out_input, &ret_input);
if (out_header_size)
*out_header_size = header_size;
return TRUE;
}
/**
* ostree_raw_file_to_archive_z2_stream:
* @input: File raw content stream
* @file_info: A file info
* @xattrs: (allow-none): Optional extended attributes
* @out_input: (out): Serialized object stream
* @cancellable: Cancellable
* @error: Error
*
* Convert from a "bare" file representation into an
* OSTREE_OBJECT_TYPE_FILE stream suitable for ostree pull.
*/
gboolean
ostree_raw_file_to_archive_z2_stream (GInputStream *input,
GFileInfo *file_info,
GVariant *xattrs,
GInputStream **out_input,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GVariant) file_header = NULL;
g_autoptr(GInputStream) zlib_input = NULL;
file_header = _ostree_zlib_file_header_new (file_info, xattrs);
if (input != NULL)
{
g_autoptr(GConverter) zlib_compressor = NULL;
zlib_compressor = G_CONVERTER (g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW, 9));
zlib_input = g_converter_input_stream_new (input, zlib_compressor);
}
return header_and_input_to_stream (file_header,
zlib_input,
out_input,
NULL,
cancellable,
error);
}
/**
* ostree_raw_file_to_content_stream:
* @input: File raw content stream
@@ -423,44 +515,20 @@ ostree_raw_file_to_content_stream (GInputStream *input,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gpointer header_data;
gsize header_size;
g_autoptr(GInputStream) ret_input = NULL;
g_autoptr(GVariant) file_header = NULL;
g_autoptr(GPtrArray) streams = NULL;
g_autoptr(GOutputStream) header_out_stream = NULL;
g_autoptr(GInputStream) header_in_stream = NULL;
guint64 header_size;
file_header = file_header_new (file_info, xattrs);
header_out_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
if (!_ostree_write_variant_with_size (header_out_stream, file_header, 0, NULL, NULL,
cancellable, error))
goto out;
if (!g_output_stream_close (header_out_stream, cancellable, error))
goto out;
header_size = g_memory_output_stream_get_data_size ((GMemoryOutputStream*) header_out_stream);
header_data = g_memory_output_stream_steal_data ((GMemoryOutputStream*) header_out_stream);
header_in_stream = g_memory_input_stream_new_from_data (header_data, header_size, g_free);
streams = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
g_ptr_array_add (streams, g_object_ref (header_in_stream));
if (input)
g_ptr_array_add (streams, g_object_ref (input));
ret_input = (GInputStream*)ostree_chain_input_stream_new (streams);
ret = TRUE;
ot_transfer_out_value (out_input, &ret_input);
if (!header_and_input_to_stream (file_header,
input,
out_input,
&header_size,
cancellable,
error))
return FALSE;
if (out_length)
*out_length = header_size + g_file_info_get_size (file_info);
out:
return ret;
return TRUE;
}
/**
@@ -613,7 +681,7 @@ ostree_content_file_parse_at (gboolean compressed,
cancellable, error))
goto out;
if (!gs_stream_fstat ((GFileDescriptorBased*)file_input, &stbuf, cancellable, error))
if (!glnx_stream_fstat ((GFileDescriptorBased*)file_input, &stbuf, error))
goto out;
if (!ostree_content_stream_parse (compressed, file_input, stbuf.st_size, trusted,
@@ -921,14 +989,13 @@ _ostree_make_temporary_symlink_at (int tmp_dirfd,
GError **error)
{
gboolean ret = FALSE;
g_autofree char *tmpname = NULL;
char *tmpname = g_strdup ("tmplink.XXXXXX");
guint i;
const int max_attempts = 128;
for (i = 0; i < max_attempts; i++)
{
g_free (tmpname);
tmpname = gs_fileutil_gen_tmp_name (NULL, NULL);
glnx_gen_temp_name (tmpname);
if (symlinkat (target, tmp_dirfd, tmpname) < 0)
{
if (errno == EEXIST)
+37 -29
View File
@@ -59,7 +59,7 @@ G_BEGIN_DECLS
* @OSTREE_OBJECT_TYPE_DIR_TREE: List of children (trees or files), and metadata
* @OSTREE_OBJECT_TYPE_DIR_META: Directory metadata
* @OSTREE_OBJECT_TYPE_COMMIT: Toplevel object, refers to tree and dirmeta for root
* @OSTREE_OBJECT_TYPE_COMMIT_TOMBSTONE: Toplevel object, refers to a deleted commit
* @OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT: Toplevel object, refers to a deleted commit
*
* Enumeration for core object types; %OSTREE_OBJECT_TYPE_FILE is for
* content, the other types are metadata.
@@ -90,10 +90,10 @@ typedef enum {
/**
* OSTREE_DIRMETA_GVARIANT_FORMAT:
*
* u - uid
* u - gid
* u - mode
* a(ayay) - xattrs
* - u - uid
* - u - gid
* - u - mode
* - a(ayay) - xattrs
*/
#define OSTREE_DIRMETA_GVARIANT_STRING "(uuua(ayay))"
#define OSTREE_DIRMETA_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_DIRMETA_GVARIANT_STRING)
@@ -106,10 +106,10 @@ typedef enum {
* can't store in the real filesystem but we can still use a regular .file object
* that we can hardlink to in the case of a user-mode checkout.
*
* u - uid
* u - gid
* u - mode
* a(ayay) - xattrs
* - u - uid
* - u - gid
* - u - mode
* - a(ayay) - xattrs
*/
#define OSTREE_FILEMETA_GVARIANT_STRING "(uuua(ayay))"
#define OSTREE_FILEMETA_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_FILEMETA_GVARIANT_STRING)
@@ -117,8 +117,8 @@ typedef enum {
/**
* OSTREE_TREE_GVARIANT_FORMAT:
*
* a(say) - array of (filename, checksum) for files
* a(sayay) - array of (dirname, tree_checksum, meta_checksum) for directories
* - a(say) - array of (filename, checksum) for files
* - a(sayay) - array of (dirname, tree_checksum, meta_checksum) for directories
*/
#define OSTREE_TREE_GVARIANT_STRING "(a(say)a(sayay))"
#define OSTREE_TREE_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_TREE_GVARIANT_STRING)
@@ -126,14 +126,14 @@ typedef enum {
/**
* OSTREE_COMMIT_GVARIANT_FORMAT:
*
* a{sv} - Metadata
* ay - parent checksum (empty string for initial)
* a(say) - Related objects
* s - subject
* s - body
* t - Timestamp in seconds since the epoch (UTC)
* ay - Root tree contents
* ay - Root tree metadata
* - a{sv} - Metadata
* - ay - parent checksum (empty string for initial)
* - a(say) - Related objects
* - s - subject
* - s - body
* - t - Timestamp in seconds since the epoch (UTC)
* - ay - Root tree contents
* - ay - Root tree metadata
*/
#define OSTREE_COMMIT_GVARIANT_STRING "(a{sv}aya(say)sstayay)"
#define OSTREE_COMMIT_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_COMMIT_GVARIANT_STRING)
@@ -141,8 +141,9 @@ typedef enum {
/**
* OSTREE_SUMMARY_GVARIANT_FORMAT:
*
* refs: a(s(taya{sv})) - Map of ref name -> (latest commit size, latest commit checksum, additional metadata), sorted by ref name
* extensions: a{sv} - Additional metadata, none defined at the current time
* - a(s(taya{sv})) - Map of ref name -> (latest commit size, latest commit checksum, additional metadata), sorted by ref name
* - a{sv} - Additional metadata, at the current time the following are defined:
* - key: "ostree.static-deltas", value: a{sv}, static delta name -> 32 bytes of checksum
*/
#define OSTREE_SUMMARY_GVARIANT_STRING "(a(s(taya{sv}))a{sv})"
#define OSTREE_SUMMARY_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_SUMMARY_GVARIANT_STRING)
@@ -152,9 +153,9 @@ typedef enum {
/**
* OstreeRepoMode:
* @OSTREE_REPO_MODE_BARE: Files are stored as themselves; can only be written as root
* @OSTREE_REPO_MODE_BARE: Files are stored as themselves; checkouts are hardlinks; can only be written as root
* @OSTREE_REPO_MODE_ARCHIVE_Z2: Files are compressed, should be owned by non-root. Can be served via HTTP
* @OSTREE_REPO_MODE_BARE_USER: Files are stored as themselves, except ownership; can be written by user
* @OSTREE_REPO_MODE_BARE_USER: Files are stored as themselves, except ownership; can be written by user. Hardlinks work only in user checkouts.
*
* See the documentation of #OstreeRepo for more information about the
* possible modes.
@@ -165,8 +166,8 @@ typedef enum {
OSTREE_REPO_MODE_BARE_USER
} OstreeRepoMode;
const _OSTREE_PUBLIC
GVariantType *ostree_metadata_variant_type (OstreeObjectType objtype);
_OSTREE_PUBLIC
const GVariantType *ostree_metadata_variant_type (OstreeObjectType objtype);
_OSTREE_PUBLIC
gboolean ostree_validate_checksum_string (const char *sha256,
@@ -214,9 +215,6 @@ gboolean ostree_parse_refspec (const char *refspec,
char **out_ref,
GError **error);
_OSTREE_PUBLIC
void ostree_checksum_update_meta (GChecksum *checksum, GFileInfo *file_info, GVariant *xattrs);
_OSTREE_PUBLIC
const char * ostree_object_type_to_string (OstreeObjectType objtype);
@@ -244,7 +242,8 @@ void ostree_object_from_string (const char *str,
gchar **out_checksum,
OstreeObjectType *out_objtype);
_OSTREE_PUBLIC gboolean
_OSTREE_PUBLIC
gboolean
ostree_content_stream_parse (gboolean compressed,
GInputStream *input,
guint64 input_length,
@@ -276,6 +275,15 @@ gboolean ostree_content_file_parse_at (gboolean compressed,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
gboolean
ostree_raw_file_to_archive_z2_stream (GInputStream *input,
GFileInfo *file_info,
GVariant *xattrs,
GInputStream **out_input,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_raw_file_to_content_stream (GInputStream *input,
GFileInfo *file_info,
+23 -9
View File
@@ -24,19 +24,33 @@
G_BEGIN_DECLS
/**
* OstreeDeployment:
* @parent_instance:
* @index: Global offset
* @osname:
* @csum: OSTree checksum of tree
* @deployserial: How many times this particular csum appears in deployment list
* @bootcsum: Checksum of kernel+initramfs
* @bootserial: An integer assigned to this tree per its ${bootcsum}
* @bootconfig: Bootloader configuration
* @origin: How to construct an upgraded version of this tree
* @unlocked: The unlocked state
*/
struct _OstreeDeployment
{
GObject parent_instance;
int index; /* Global offset */
char *osname; /* osname */
char *csum; /* OSTree checksum of tree */
int deployserial; /* How many times this particular csum appears in deployment list */
char *bootcsum; /* Checksum of kernel+initramfs */
int bootserial; /* An integer assigned to this tree per its ${bootcsum} */
OstreeBootconfigParser *bootconfig; /* Bootloader configuration */
GKeyFile *origin; /* How to construct an upgraded version of this tree */
OstreeDeploymentUnlockedState unlocked; /* The unlocked state */
int index;
char *osname;
char *csum;
int deployserial;
char *bootcsum;
int bootserial;
OstreeBootconfigParser *bootconfig;
GKeyFile *origin;
OstreeDeploymentUnlockedState unlocked;
};
void _ostree_deployment_set_bootcsum (OstreeDeployment *self, const char *bootcsum);
+3
View File
@@ -22,6 +22,7 @@
#include "config.h"
#include "libglnx.h"
#include "ostree.h"
#include "otutil.h"
@@ -209,6 +210,8 @@ diff_add_dir_recurse (GFile *d,
* @modified: (element-type OstreeDiffItem): Modified files
* @removed: (element-type Gio.File): Removed files
* @added: (element-type Gio.File): Added files
* @cancellable: Cancellable
* @error: Error
*
* Compute the difference between directory @a and @b as 3 separate
* sets of #OstreeDiffItem in @modified, @removed, and @added.
+6
View File
@@ -27,11 +27,17 @@
G_BEGIN_DECLS
/**
* OstreeDiffFlags:
*/
typedef enum {
OSTREE_DIFF_FLAGS_NONE = 0,
OSTREE_DIFF_FLAGS_IGNORE_XATTRS = (1 << 0)
} OstreeDiffFlags;
/**
* OstreeDiffItem:
*/
typedef struct _OstreeDiffItem OstreeDiffItem;
struct _OstreeDiffItem
{
+31
View File
@@ -0,0 +1,31 @@
/* This file declares a stub function that is only exported
* to pacify ABI checkers - no one could really have used it.
*
* Copyright (C) 2016 Red Hat, Inc.
*
* 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 "ostree-dummy-enumtypes.h"
/* Exported for backwards compat - see
* https://bugzilla.gnome.org/show_bug.cgi?id=764131
*/
GType
ostree_fetcher_config_flags_get_type (void)
{
return G_TYPE_INVALID;
}
+29
View File
@@ -0,0 +1,29 @@
/* This file declares a stub function that is only exported
* to pacify ABI checkers - no one could really have used it.
*
* Copyright (C) 2016 Red Hat, Inc.
*
* 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.
*/
#pragma once
#include <glib-object.h>
#ifndef __GI_SCANNER__
_OSTREE_PUBLIC GType
ostree_fetcher_config_flags_get_type (void);
#endif
+1 -1
View File
@@ -28,7 +28,7 @@
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
_@enum_name@_get_type (void)
{
static volatile gsize the_type__volatile = 0;
+2 -3
View File
@@ -32,9 +32,8 @@ G_BEGIN_DECLS
/*** END file-production ***/
/*** BEGIN enumeration-production ***/
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
_OSTREE_PUBLIC
GType @enum_name@_get_type (void) G_GNUC_CONST;
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (_@enum_name@_get_type ())
GType _@enum_name@_get_type (void) G_GNUC_CONST;
/*** END enumeration-production ***/
+53 -11
View File
@@ -25,6 +25,7 @@
#include <gio/gfiledescriptorbased.h>
#include <gio/gunixoutputstream.h>
#include "libglnx.h"
#include "ostree-fetcher.h"
#ifdef HAVE_LIBSOUP_CLIENT_CERTS
#include "ostree-tls-cert-interaction.h"
@@ -66,7 +67,12 @@ typedef struct {
guint64 total_downloaded;
} ThreadClosure;
static void
session_thread_process_pending_queue (ThreadClosure *thread_closure);
typedef struct {
volatile int ref_count;
ThreadClosure *thread_closure;
SoupURI *uri;
@@ -185,10 +191,22 @@ pending_task_compare (gconstpointer a,
(priority_a < priority_b) ? -1 : 1;
}
static void
pending_uri_free (OstreeFetcherPendingURI *pending)
static OstreeFetcherPendingURI *
pending_uri_ref (OstreeFetcherPendingURI *pending)
{
g_hash_table_remove (pending->thread_closure->outstanding, pending);
g_return_val_if_fail (pending != NULL, NULL);
g_return_val_if_fail (pending->ref_count > 0, NULL);
g_atomic_int_inc (&pending->ref_count);
return pending;
}
static void
pending_uri_unref (OstreeFetcherPendingURI *pending)
{
if (!g_atomic_int_dec_and_test (&pending->ref_count))
return;
g_clear_pointer (&pending->thread_closure, thread_closure_unref);
@@ -273,6 +291,7 @@ session_thread_set_proxy_cb (ThreadClosure *thread_closure,
proxy_uri, NULL);
}
#ifdef HAVE_LIBSOUP_CLIENT_CERTS
static void
session_thread_set_tls_interaction_cb (ThreadClosure *thread_closure,
gpointer data)
@@ -288,6 +307,7 @@ session_thread_set_tls_interaction_cb (ThreadClosure *thread_closure,
SOUP_SESSION_TLS_INTERACTION,
interaction, NULL);
}
#endif
static void
session_thread_set_tls_database_cb (ThreadClosure *thread_closure,
@@ -328,8 +348,7 @@ session_thread_process_pending_queue (ThreadClosure *thread_closure)
pending = g_task_get_task_data (task);
cancellable = g_task_get_cancellable (task);
/* pending_uri_free() removes this. */
g_hash_table_add (thread_closure->outstanding, pending);
g_hash_table_add (thread_closure->outstanding, pending_uri_ref (pending));
soup_request_send_async (pending->request,
cancellable,
@@ -383,7 +402,7 @@ session_thread_request_uri (ThreadClosure *thread_closure,
if (thread_closure->tmpdir_name == NULL)
{
if (!_ostree_repo_allocate_tmpdir (thread_closure->base_tmpdir_dfd,
"fetcher-",
OSTREE_REPO_TMPDIR_FETCHER,
&thread_closure->tmpdir_name,
&thread_closure->tmpdir_dfd,
&thread_closure->tmpdir_lock,
@@ -537,7 +556,7 @@ _ostree_fetcher_constructed (GObject *object)
self->thread_closure->tmpdir_dfd = -1;
self->thread_closure->tmpdir_lock = empty_lockfile;
self->thread_closure->outstanding = g_hash_table_new (NULL, NULL);
self->thread_closure->outstanding = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)pending_uri_unref);
self->thread_closure->output_stream_set = g_hash_table_new_full (NULL, NULL,
(GDestroyNotify) NULL,
(GDestroyNotify) g_object_unref);
@@ -739,6 +758,18 @@ on_stream_read (GObject *object,
GAsyncResult *result,
gpointer user_data);
static void
remove_pending_rerun_queue (OstreeFetcherPendingURI *pending)
{
/* Hold a temporary ref to ensure the reference to
* pending->thread_closure is valid.
*/
pending_uri_ref (pending);
g_hash_table_remove (pending->thread_closure->outstanding, pending);
session_thread_process_pending_queue (pending->thread_closure);
pending_uri_unref (pending);
}
static void
on_out_splice_complete (GObject *object,
GAsyncResult *result,
@@ -767,7 +798,10 @@ on_out_splice_complete (GObject *object,
out:
if (local_error)
g_task_return_error (task, local_error);
{
g_task_return_error (task, local_error);
remove_pending_rerun_queue (pending);
}
g_object_unref (task);
}
@@ -799,6 +833,7 @@ on_stream_read (GObject *object,
g_task_return_pointer (task,
g_strdup (pending->out_tmpfile),
(GDestroyNotify) g_free);
remove_pending_rerun_queue (pending);
}
else
{
@@ -834,7 +869,10 @@ on_stream_read (GObject *object,
out:
if (local_error)
g_task_return_error (task, local_error);
{
g_task_return_error (task, local_error);
remove_pending_rerun_queue (pending);
}
g_object_unref (task);
}
@@ -880,6 +918,7 @@ on_request_sent (GObject *object,
g_strdup (pending->out_tmpfile),
(GDestroyNotify) g_free);
}
remove_pending_rerun_queue (pending);
goto out;
}
else if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
@@ -944,6 +983,7 @@ on_request_sent (GObject *object,
g_task_return_pointer (task,
g_object_ref (pending->request_body),
(GDestroyNotify) g_object_unref);
remove_pending_rerun_queue (pending);
}
out:
@@ -952,6 +992,7 @@ on_request_sent (GObject *object,
if (pending->request_body)
(void) g_input_stream_close (pending->request_body, NULL, NULL);
g_task_return_error (task, local_error);
remove_pending_rerun_queue (pending);
}
g_object_unref (task);
@@ -976,6 +1017,7 @@ ostree_fetcher_request_uri_internal (OstreeFetcher *self,
/* SoupRequest is created in session thread. */
pending = g_new0 (OstreeFetcherPendingURI, 1);
pending->ref_count = 1;
pending->thread_closure = thread_closure_ref (self->thread_closure);
pending->uri = soup_uri_copy (uri);
pending->max_size = max_size;
@@ -983,7 +1025,7 @@ ostree_fetcher_request_uri_internal (OstreeFetcher *self,
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, source_tag);
g_task_set_task_data (task, pending, (GDestroyNotify) pending_uri_free);
g_task_set_task_data (task, pending, (GDestroyNotify) pending_uri_unref);
/* We'll use the GTask priority for our own priority queue. */
g_task_set_priority (task, priority);
@@ -1067,7 +1109,7 @@ _ostree_fetcher_bytes_transferred (OstreeFetcher *self)
if (G_IS_FILE_DESCRIPTOR_BASED (stream))
{
if (gs_stream_fstat ((GFileDescriptorBased*)stream, &stbuf, NULL, NULL))
if (glnx_stream_fstat ((GFileDescriptorBased*)stream, &stbuf, NULL))
ret += stbuf.st_size;
}
}
+5
View File
@@ -35,6 +35,11 @@ G_BEGIN_DECLS
typedef struct OstreeGpgVerifier OstreeGpgVerifier;
/* If this type becomes public in future, move this autoptr cleanup
* definition to the ostree-autocleanups.h header file. Right now it
* relies on glnx's fallback definition of the macro. */
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeGpgVerifier, g_object_unref)
GType _ostree_gpg_verifier_get_type (void);
OstreeGpgVerifier *_ostree_gpg_verifier_new (void);
+31 -1
View File
@@ -27,7 +27,7 @@
#include "ostree-gpg-verify-result-private.h"
/**
* SECTION: libostree-gpg-verify-result
* SECTION: ostree-gpg-verify-result
* @title: GPG signature verification results
* @short_description: Inspect detached GPG signatures
*
@@ -622,3 +622,33 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
}
}
}
/**
* ostree_gpg_verify_result_require_valid_signature:
* @result: (nullable): an #OstreeGpgVerifyResult
* @error: A #GError
*
* Checks if the result contains at least one signature from the
* trusted keyring. You can call this function immediately after
* ostree_repo_verify_summary() or ostree_repo_verify_commit_ext() -
* it will handle the %NULL @result and filled @error too.
*
* Returns: %TRUE if @result was not %NULL and had at least one
* signature from trusted keyring, otherwise %FALSE
*/
gboolean
ostree_gpg_verify_result_require_valid_signature (OstreeGpgVerifyResult *result,
GError **error)
{
if (result == NULL)
return FALSE;
if (ostree_gpg_verify_result_count_valid (result) == 0)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"GPG signatures found, but none are in trusted keyring");
return FALSE;
}
return TRUE;
}
+4
View File
@@ -133,4 +133,8 @@ void ostree_gpg_verify_result_describe_variant (GVariant *variant,
const gchar *line_prefix,
OstreeGpgSignatureFormatFlags flags);
_OSTREE_PUBLIC
gboolean ostree_gpg_verify_result_require_valid_signature (OstreeGpgVerifyResult *result,
GError **error);
G_END_DECLS
+1 -3
View File
@@ -107,7 +107,7 @@ _ostree_linuxfs_alter_immutable_flag (GFile *path,
GError **error)
{
gboolean ret = FALSE;
int fd = -1;
glnx_fd_close int fd = -1;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@@ -129,7 +129,5 @@ _ostree_linuxfs_alter_immutable_flag (GFile *path,
ret = TRUE;
out:
if (fd != -1)
(void) close (fd);
return ret;
}
+1 -1
View File
@@ -32,7 +32,7 @@ enum {
/**
* SECTION:ostree-lzma-compressor
* @short_description: LZMA compressor
* @title: LZMA compressor
*
* An implementation of #GConverter that compresses data using
* LZMA.
+8
View File
@@ -29,6 +29,14 @@ enum {
PROP_0,
};
/**
* SECTION:ostree-lzma-decompressor
* @title: LZMA decompressor
*
* An implementation of #GConverter that decompresses data using
* LZMA.
*/
static void _ostree_lzma_decompressor_iface_init (GConverterIface *iface);
struct _OstreeLzmaDecompressor
+9 -1
View File
@@ -27,7 +27,7 @@
#include "ostree-core.h"
/**
* SECTION:libostree-mutable-tree
* SECTION:ostree-mutable-tree
* @title: In-memory modifiable filesystem tree
* @short_description: Modifiable filesystem tree
*
@@ -159,6 +159,11 @@ ostree_mutable_tree_replace_file (OstreeMutableTree *self,
{
gboolean ret = FALSE;
g_return_val_if_fail (name != NULL, FALSE);
if (!ot_util_filename_validate (name, error))
goto out;
if (g_hash_table_lookup (self->subdirs, name))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -187,6 +192,9 @@ ostree_mutable_tree_ensure_dir (OstreeMutableTree *self,
g_return_val_if_fail (name != NULL, FALSE);
if (!ot_util_filename_validate (name, error))
goto out;
if (g_hash_table_lookup (self->files, name))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+2 -1
View File
@@ -84,7 +84,8 @@ gboolean ostree_mutable_tree_lookup (OstreeMutableTree *self,
OstreeMutableTree **out_subdir,
GError **error);
_OSTREE_PUBLIC gboolean
_OSTREE_PUBLIC
gboolean
ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree *self,
GPtrArray *split_path,
const char *metadata_checksum,
+25 -29
View File
@@ -632,7 +632,7 @@ checkout_tree_at (OstreeRepo *self,
{
gboolean ret = FALSE;
gboolean did_exist = FALSE;
int destination_dfd = -1;
glnx_fd_close int destination_dfd = -1;
int res;
g_autoptr(GVariant) xattrs = NULL;
g_autoptr(GFileEnumerator) dir_enum = NULL;
@@ -752,12 +752,12 @@ checkout_tree_at (OstreeRepo *self,
}
}
/* Set directory mtime to 0, so that it is constant for all checkouts.
/* Set directory mtime to OSTREE_TIMESTAMP, so that it is constant for all checkouts.
* Must be done after setting permissions and creating all children.
*/
if (!did_exist)
{
const struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, } };
const struct timespec times[2] = { { OSTREE_TIMESTAMP, UTIME_OMIT }, { OSTREE_TIMESTAMP, 0} };
do
res = futimens (destination_dfd, times);
while (G_UNLIKELY (res == -1 && errno == EINTR));
@@ -779,8 +779,6 @@ checkout_tree_at (OstreeRepo *self,
ret = TRUE;
out:
if (destination_dfd != -1)
(void) close (destination_dfd);
return ret;
}
@@ -957,38 +955,36 @@ ostree_repo_checkout_gc (OstreeRepo *self,
g_hash_table_iter_init (&iter, to_clean_dirs);
while (to_clean_dirs && g_hash_table_iter_next (&iter, &key, &value))
{
g_autoptr(GFile) objdir = NULL;
g_autoptr(GFileEnumerator) enumerator = NULL;
g_autofree char *objdir_name = NULL;
g_autofree char *objdir_name = g_strdup_printf ("%02x", GPOINTER_TO_UINT (key));
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
objdir_name = g_strdup_printf ("%02x", GPOINTER_TO_UINT (key));
objdir = g_file_get_child (self->uncompressed_objects_dir, objdir_name);
enumerator = g_file_enumerate_children (objdir, "standard::name,standard::type,unix::inode,unix::nlink",
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable,
error);
if (!enumerator)
if (!glnx_dirfd_iterator_init_at (self->uncompressed_objects_dir_fd, objdir_name, FALSE,
&dfd_iter, error))
goto out;
while (TRUE)
{
GFileInfo *file_info;
guint32 nlinks;
struct dirent *dent;
struct stat stbuf;
if (!gs_file_enumerator_iterate (enumerator, &file_info, NULL,
cancellable, error))
if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
goto out;
if (file_info == NULL)
if (dent == NULL)
break;
nlinks = g_file_info_get_attribute_uint32 (file_info, "unix::nlink");
if (nlinks == 1)
if (fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) != 0)
{
g_autoptr(GFile) objpath = NULL;
objpath = g_file_get_child (objdir, g_file_info_get_name (file_info));
if (!gs_file_unlink (objpath, cancellable, error))
goto out;
glnx_set_error_from_errno (error);
goto out;
}
if (stbuf.st_nlink == 1)
{
if (unlinkat (dfd_iter.fd, dent->d_name, 0) != 0)
{
glnx_set_error_from_errno (error);
goto out;
}
}
}
}
+104 -82
View File
@@ -36,22 +36,6 @@
#include <sys/xattr.h>
#include <glib/gprintf.h>
struct OstreeRepoCommitModifier {
volatile gint refcount;
OstreeRepoCommitModifierFlags flags;
OstreeRepoCommitFilter filter;
gpointer user_data;
GDestroyNotify destroy_notify;
OstreeRepoCommitModifierXattrCallback xattr_callback;
GDestroyNotify xattr_destroy;
gpointer xattr_user_data;
OstreeSePolicy *sepolicy;
GHashTable *devino_cache;
};
gboolean
_ostree_repo_ensure_loose_objdir_at (int dfd,
const char *loose_path,
@@ -226,7 +210,6 @@ commit_loose_object_trusted (OstreeRepo *self,
else
{
int res;
struct timespec times[2];
if (objtype == OSTREE_OBJECT_TYPE_FILE && self->mode == OSTREE_REPO_MODE_BARE)
{
@@ -282,12 +265,9 @@ commit_loose_object_trusted (OstreeRepo *self,
{
/* To satisfy tools such as guile which compare mtimes
* to determine whether or not source files need to be compiled,
* set the modification time to 0.
* set the modification time to OSTREE_TIMESTAMP.
*/
times[0].tv_sec = 0; /* atime */
times[0].tv_nsec = UTIME_OMIT;
times[1].tv_sec = 0; /* mtime */
times[1].tv_nsec = 0;
const struct timespec times[2] = { { OSTREE_TIMESTAMP, UTIME_OMIT }, { OSTREE_TIMESTAMP, 0} };
do
res = futimens (fd, times);
while (G_UNLIKELY (res == -1 && errno == EINTR));
@@ -573,11 +553,8 @@ _ostree_repo_open_trusted_content_bare (OstreeRepo *self,
g_autofree char *temp_filename = NULL;
g_autoptr(GOutputStream) ret_stream = NULL;
gboolean have_obj;
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
if (!_ostree_repo_has_loose_object (self, checksum, OSTREE_OBJECT_TYPE_FILE,
&have_obj, loose_objpath,
NULL,
if (!_ostree_repo_has_loose_object (self, checksum, OSTREE_OBJECT_TYPE_FILE, &have_obj,
cancellable, error))
goto out;
@@ -662,7 +639,6 @@ write_object (OstreeRepo *self,
gboolean temp_file_is_regular;
gboolean temp_file_is_symlink;
gboolean object_is_symlink = FALSE;
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
gssize unpacked_size = 0;
gboolean indexable = FALSE;
@@ -673,9 +649,8 @@ write_object (OstreeRepo *self,
if (expected_checksum)
{
if (!_ostree_repo_has_loose_object (self, expected_checksum, objtype,
&have_obj, loose_objpath,
NULL, cancellable, error))
if (!_ostree_repo_has_loose_object (self, expected_checksum, objtype, &have_obj,
cancellable, error))
goto out;
if (have_obj)
{
@@ -852,8 +827,7 @@ write_object (OstreeRepo *self,
repo_store_size_entry (self, actual_checksum, unpacked_size, stbuf.st_size);
}
if (!_ostree_repo_has_loose_object (self, actual_checksum, objtype,
&have_obj, loose_objpath, NULL,
if (!_ostree_repo_has_loose_object (self, actual_checksum, objtype, &have_obj,
cancellable, error))
goto out;
@@ -1167,7 +1141,6 @@ ostree_repo_prepare_transaction (OstreeRepo *self,
{
gboolean ret = FALSE;
gboolean ret_transaction_resume = FALSE;
g_autofree char *stagedir_boot_id_prefix = NULL;
g_autofree char *stagedir_name = NULL;
glnx_fd_close int stagedir_fd = -1;
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
@@ -1178,10 +1151,8 @@ ostree_repo_prepare_transaction (OstreeRepo *self,
self->in_transaction = TRUE;
stagedir_boot_id_prefix = g_strconcat ("staging-", self->boot_id, "-", NULL);
if (!_ostree_repo_allocate_tmpdir (self->tmp_dir_fd,
stagedir_boot_id_prefix,
self->stagedir_prefix,
&self->commit_stagedir_name,
&self->commit_stagedir_fd,
&self->commit_stagedir_lock,
@@ -1287,44 +1258,87 @@ cleanup_tmpdir (OstreeRepo *self,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GFileEnumerator) enumerator = NULL;
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
guint64 curtime_secs;
enumerator = g_file_enumerate_children (self->tmp_dir, "standard::name,time::modified",
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable,
error);
if (!enumerator)
goto out;
curtime_secs = g_get_real_time () / 1000000;
if (!glnx_dirfd_iterator_init_at (self->tmp_dir_fd, ".", TRUE, &dfd_iter, error))
goto out;
while (TRUE)
{
GFileInfo *file_info;
GFile *path;
guint64 mtime;
guint64 delta;
struct dirent *dent;
struct stat stbuf;
g_auto(GLnxLockFile) lockfile = GLNX_LOCK_FILE_INIT;
gboolean did_lock;
if (!gs_file_enumerator_iterate (enumerator, &file_info, &path,
cancellable, error))
if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
goto out;
if (file_info == NULL)
if (dent == NULL)
break;
mtime = g_file_info_get_attribute_uint64 (file_info, "time::modified");
if (mtime > curtime_secs)
continue;
/* Only delete files older than a day. To do better, we would
* need to coordinate between multiple processes in a reliable
* fashion. See
* https://bugzilla.gnome.org/show_bug.cgi?id=709115
*/
delta = curtime_secs - mtime;
if (delta > 60*60*24)
if (TEMP_FAILURE_RETRY (fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW)) < 0)
{
if (!glnx_shutil_rm_rf_at (AT_FDCWD, gs_file_get_path_cached (path), cancellable, error))
if (errno == ENOENT) /* Did another cleanup win? */
continue;
glnx_set_error_from_errno (error);
goto out;
}
/* First, if it's a directory which needs locking, but it's
* busy, skip it.
*/
if (_ostree_repo_is_locked_tmpdir (dent->d_name))
{
if (!_ostree_repo_try_lock_tmpdir (dfd_iter.fd, dent->d_name,
&lockfile, &did_lock, error))
goto out;
if (!did_lock)
continue;
}
/* If however this is the staging directory for the *current*
* boot, then don't delete it now - we may end up reusing it, as
* is the point.
*/
if (g_str_has_prefix (dent->d_name, self->stagedir_prefix))
continue;
else if (g_str_has_prefix (dent->d_name, OSTREE_REPO_TMPDIR_STAGING))
{
/* But, crucially we can now clean up staging directories
* from *other* boots
*/
if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error))
goto out;
}
/* FIXME - move OSTREE_REPO_TMPDIR_FETCHER underneath the
* staging/boot-id scheme as well, since all of the "did it get
* fsync'd" concerns apply to that as well. Then we can skip
* this special case.
*/
else if (g_str_has_prefix (dent->d_name, OSTREE_REPO_TMPDIR_FETCHER))
continue;
else
{
/* Now we do time-based cleanup. Ignore it if it's somehow
* in the future...
*/
if (stbuf.st_mtime > curtime_secs)
continue;
/* Now, we're pruning content based on the expiry, which
* defaults to a day. That's what we were doing before we
* had locking...but in future we can be smarter here.
*/
delta = curtime_secs - stbuf.st_mtime;
if (delta > self->tmp_expiry_seconds)
{
if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error))
goto out;
}
}
}
@@ -1448,12 +1462,25 @@ ostree_repo_commit_transaction (OstreeRepo *self,
g_return_val_if_fail (self->in_transaction == TRUE, FALSE);
if (syncfs (self->tmp_dir_fd) < 0)
if ((self->test_error_flags & OSTREE_REPO_TEST_ERROR_PRE_COMMIT) > 0)
{
glnx_set_error_from_errno (error);
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"OSTREE_REPO_TEST_ERROR_PRE_COMMIT specified");
goto out;
}
/* FIXME: Added since valgrind in el7 doesn't know about
* `syncfs`...we should delete this later.
*/
if (g_getenv ("OSTREE_SUPPRESS_SYNCFS") == NULL)
{
if (syncfs (self->tmp_dir_fd) < 0)
{
glnx_set_error_from_errno (error);
goto out;
}
}
if (!rename_pending_loose_objects (self, cancellable, error))
goto out;
@@ -1937,7 +1964,7 @@ create_empty_gvariant_dict (void)
* ostree_repo_write_commit:
* @self: Repo
* @parent: (allow-none): ASCII SHA256 checksum for parent, or %NULL for none
* @subject: Subject
* @subject: (allow-none): Subject
* @body: (allow-none): Body
* @metadata: (allow-none): GVariant of type a{sv}, or %NULL for none
* @root: The tree to point the commit to
@@ -1981,10 +2008,11 @@ ostree_repo_write_commit (OstreeRepo *self,
* ostree_repo_write_commit_with_time:
* @self: Repo
* @parent: (allow-none): ASCII SHA256 checksum for parent, or %NULL for none
* @subject: Subject
* @subject: (allow-none): Subject
* @body: (allow-none): Body
* @metadata: (allow-none): GVariant of type a{sv}, or %NULL for none
* @root: The tree to point the commit to
* @time: The time to use to stamp the commit
* @out_commit: (out): Resulting ASCII SHA256 checksum for commit
* @cancellable: Cancellable
* @error: Error
@@ -2011,8 +2039,6 @@ ostree_repo_write_commit_with_time (OstreeRepo *self,
g_autofree guchar *commit_csum = NULL;
OstreeRepoFile *repo_root = OSTREE_REPO_FILE (root);
g_return_val_if_fail (subject != NULL, FALSE);
/* Add sizes information to our metadata object */
if (!add_size_index_to_metadata (self, metadata, &new_metadata,
cancellable, error))
@@ -2022,7 +2048,7 @@ ostree_repo_write_commit_with_time (OstreeRepo *self,
new_metadata ? new_metadata : create_empty_gvariant_dict (),
parent ? ostree_checksum_to_bytes_v (parent) : ot_gvariant_new_bytearray (NULL, 0),
g_variant_new_array (G_VARIANT_TYPE ("(say)"), NULL, 0),
subject, body ? body : "",
subject ? subject : "", body ? body : "",
GUINT64_TO_BE (time),
ostree_checksum_to_bytes_v (ostree_repo_file_tree_get_contents_checksum (repo_root)),
ostree_checksum_to_bytes_v (ostree_repo_file_tree_get_metadata_checksum (repo_root)));
@@ -2073,21 +2099,13 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self,
g_autoptr(GFile) metadata_path =
_ostree_repo_get_commit_metadata_loose_path (self, checksum);
g_autoptr(GVariant) ret_metadata = NULL;
GError *temp_error = NULL;
if (!ot_util_variant_map (metadata_path, G_VARIANT_TYPE ("a{sv}"),
TRUE, &ret_metadata, &temp_error))
if (!ot_util_variant_map_at (AT_FDCWD, gs_file_get_path_cached (metadata_path),
G_VARIANT_TYPE ("a{sv}"),
OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&temp_error);
}
else
{
g_prefix_error (error, "Unable to read existing detached metadata: ");
g_propagate_error (error, temp_error);
goto out;
}
g_prefix_error (error, "Unable to read existing detached metadata: ");
goto out;
}
ret = TRUE;
@@ -2184,6 +2202,10 @@ create_tree_variant_from_hashes (GHashTable *file_checksums,
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
const char *name = key;
/* Should have been validated earlier, but be paranoid */
g_assert (ot_util_filename_validate (name, NULL));
sorted_filenames = g_slist_prepend (sorted_filenames, (char*)name);
}
@@ -2355,7 +2377,7 @@ get_modified_xattrs (OstreeRepo *self,
if (label)
{
GVariantBuilder *builder;
g_autoptr(GVariantBuilder) builder = NULL;
/* ret_xattrs may be NULL */
builder = ot_util_variant_builder_from_variant (ret_xattrs,
-3
View File
@@ -58,9 +58,6 @@ OstreeRepo * ostree_repo_file_get_repo (OstreeRepoFile *self);
_OSTREE_PUBLIC
OstreeRepoFile * ostree_repo_file_get_root (OstreeRepoFile *self);
_OSTREE_PUBLIC
void ostree_repo_file_make_empty_tree (OstreeRepoFile *self);
_OSTREE_PUBLIC
void ostree_repo_file_tree_set_metadata (OstreeRepoFile *self,
const char *checksum,
File diff suppressed because it is too large. Load diff
+39 -32
View File
@@ -23,10 +23,6 @@
#include "ostree-repo.h"
#include "libglnx.h"
#ifdef HAVE_LIBSOUP
#include "ostree-fetcher.h"
#endif
G_BEGIN_DECLS
#define OSTREE_DELTAPART_VERSION (0)
@@ -36,6 +32,28 @@ G_BEGIN_DECLS
#define _OSTREE_SUMMARY_CACHE_DIR "summaries"
#define _OSTREE_CACHE_DIR "cache"
#define OSTREE_TIMESTAMP (1)
typedef enum {
OSTREE_REPO_TEST_ERROR_PRE_COMMIT = (1 << 0)
} OstreeRepoTestErrorFlags;
struct OstreeRepoCommitModifier {
volatile gint refcount;
OstreeRepoCommitModifierFlags flags;
OstreeRepoCommitFilter filter;
gpointer user_data;
GDestroyNotify destroy_notify;
OstreeRepoCommitModifierXattrCallback xattr_callback;
GDestroyNotify xattr_destroy;
gpointer xattr_user_data;
OstreeSePolicy *sepolicy;
GHashTable *devino_cache;
};
/**
* OstreeRepo:
*
@@ -44,7 +62,7 @@ G_BEGIN_DECLS
struct OstreeRepo {
GObject parent;
char *boot_id;
char *stagedir_prefix;
int commit_stagedir_fd;
char *commit_stagedir_name;
GLnxLockFile commit_stagedir_lock;
@@ -86,12 +104,15 @@ struct OstreeRepo {
uid_t target_owner_uid;
gid_t target_owner_gid;
guint test_error_flags; /* OstreeRepoTestErrorFlags */
GKeyFile *config;
GHashTable *remotes;
GMutex remotes_lock;
OstreeRepoMode mode;
gboolean enable_uncompressed_cache;
gboolean generate_sizes;
guint64 tmp_expiry_seconds;
OstreeRepo *parent_repo;
};
@@ -102,6 +123,9 @@ typedef struct {
char checksum[65];
} OstreeDevIno;
#define OSTREE_REPO_TMPDIR_STAGING "staging-"
#define OSTREE_REPO_TMPDIR_FETCHER "fetcher-"
gboolean
_ostree_repo_allocate_tmpdir (int tmpdir_dfd,
const char *tmpdir_prefix,
@@ -112,6 +136,16 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd,
GCancellable *cancellable,
GError **error);
gboolean
_ostree_repo_is_locked_tmpdir (const char *filename);
gboolean
_ostree_repo_try_lock_tmpdir (int tmpdir_dfd,
const char *tmpdir_name,
GLnxLockFile *file_lock_out,
gboolean *out_did_lock,
GError **error);
gboolean
_ostree_repo_ensure_loose_objdir_at (int dfd,
const char *loose_path,
@@ -135,8 +169,6 @@ _ostree_repo_has_loose_object (OstreeRepo *self,
const char *checksum,
OstreeObjectType objtype,
gboolean *out_is_stored,
char *loose_path_buf,
GFile **out_stored_path,
GCancellable *cancellable,
GError **error);
@@ -199,13 +231,6 @@ _ostree_repo_commit_modifier_apply (OstreeRepo *self,
gboolean
_ostree_repo_remote_name_is_file (const char *remote_name);
#ifdef HAVE_LIBSOUP
OstreeFetcher *
_ostree_repo_remote_new_fetcher (OstreeRepo *self,
const char *remote_name,
GError **error);
#endif
OstreeGpgVerifyResult *
_ostree_repo_gpg_verify_with_metadata (OstreeRepo *self,
GBytes *signed_data,
@@ -293,22 +318,4 @@ gboolean
_ostree_repo_update_mtime (OstreeRepo *self,
GError **error);
/* Load the summary from the cache if the provided .sig file is the same as the
cached version. */
gboolean
_ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self,
const char *remote,
GBytes *summary_sig,
GBytes **summary,
GCancellable *cancellable,
GError **error);
gboolean
_ostree_repo_cache_summary (OstreeRepo *self,
const char *remote,
GBytes *summary,
GBytes *summary_sig,
GCancellable *cancellable,
GError **error);
G_END_DECLS
+452 -52
View File
@@ -23,11 +23,15 @@
#include "config.h"
#include "ostree.h"
#include "otutil.h"
#ifdef HAVE_LIBSOUP
#include "libglnx.h"
#include "ostree-core-private.h"
#include "ostree-repo-private.h"
#include "ostree-repo-static-delta-private.h"
#include "ostree-metalink.h"
#include "otutil.h"
#include "ot-fs-utils.h"
#include <gio/gunixinputstream.h>
@@ -629,6 +633,7 @@ content_fetch_on_write_complete (GObject *object,
const char *expected_checksum;
g_autofree guchar *csum = NULL;
g_autofree char *checksum = NULL;
g_autofree char *checksum_obj = NULL;
if (!ostree_repo_write_content_finish ((OstreeRepo*)object, result,
&csum, error))
@@ -639,7 +644,8 @@ content_fetch_on_write_complete (GObject *object,
ostree_object_name_deserialize (fetch_data->object, &expected_checksum, &objtype);
g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
g_debug ("write of %s complete", ostree_object_to_string (checksum, objtype));
checksum_obj = ostree_object_to_string (checksum, objtype);
g_debug ("write of %s complete", checksum_obj);
if (strcmp (checksum, expected_checksum) != 0)
{
@@ -675,6 +681,7 @@ content_fetch_on_complete (GObject *object,
g_autoptr(GInputStream) object_input = NULL;
g_autofree char *temp_path = NULL;
const char *checksum;
g_autofree char *checksum_obj = NULL;
OstreeObjectType objtype;
temp_path = _ostree_fetcher_request_uri_with_partial_finish (fetcher, result, error);
@@ -684,7 +691,8 @@ content_fetch_on_complete (GObject *object,
ostree_object_name_deserialize (fetch_data->object, &checksum, &objtype);
g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
g_debug ("fetch of %s complete", ostree_object_to_string (checksum, objtype));
checksum_obj = ostree_object_to_string (checksum, objtype);
g_debug ("fetch of %s complete", checksum_obj);
if (pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2)
{
@@ -796,13 +804,16 @@ meta_fetch_on_complete (GObject *object,
g_autoptr(GVariant) metadata = NULL;
g_autofree char *temp_path = NULL;
const char *checksum;
g_autofree char *checksum_obj = NULL;
OstreeObjectType objtype;
GError *local_error = NULL;
GError **error = &local_error;
glnx_fd_close int fd = -1;
gboolean free_fetch_data = FALSE;
ostree_object_name_deserialize (fetch_data->object, &checksum, &objtype);
g_debug ("fetch of %s%s complete", ostree_object_to_string (checksum, objtype),
checksum_obj = ostree_object_to_string (checksum, objtype);
g_debug ("fetch of %s%s complete", checksum_obj,
fetch_data->is_detached_meta ? " (detached)" : "");
temp_path = _ostree_fetcher_request_uri_with_partial_finish (fetcher, result, error);
@@ -864,6 +875,8 @@ meta_fetch_on_complete (GObject *object,
if (!fetch_data->object_is_stored)
enqueue_one_object_request (pull_data, checksum, objtype, FALSE, FALSE);
free_fetch_data = TRUE;
}
else
{
@@ -901,7 +914,7 @@ meta_fetch_on_complete (GObject *object,
pull_data->n_outstanding_metadata_fetches--;
pull_data->n_fetched_metadata++;
check_outstanding_requests_handle_error (pull_data, local_error);
if (local_error)
if (local_error || free_fetch_data)
{
g_variant_unref (fetch_data->object);
g_free (fetch_data);
@@ -1445,6 +1458,7 @@ request_static_delta_superblock_sync (OtPullData *pull_data,
if (out_delta_superblock)
*out_delta_superblock = g_steal_pointer (&ret_delta_superblock);
out:
g_clear_pointer (&target_uri, (GDestroyNotify) soup_uri_free);
return ret;
}
@@ -1734,47 +1748,9 @@ validate_variant_is_csum (GVariant *csum,
return ret;
}
/* documented in ostree-repo.c */
gboolean
ostree_repo_pull (OstreeRepo *self,
const char *remote_name,
char **refs_to_fetch,
OstreeRepoPullFlags flags,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error)
{
return ostree_repo_pull_one_dir (self, remote_name, NULL, refs_to_fetch, flags, progress, cancellable, error);
}
/* Documented in ostree-repo.c */
gboolean
ostree_repo_pull_one_dir (OstreeRepo *self,
const char *remote_name,
const char *dir_to_pull,
char **refs_to_fetch,
OstreeRepoPullFlags flags,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error)
{
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
if (dir_to_pull)
g_variant_builder_add (&builder, "{s@v}", "subdir",
g_variant_new_variant (g_variant_new_string (dir_to_pull)));
g_variant_builder_add (&builder, "{s@v}", "flags",
g_variant_new_variant (g_variant_new_int32 (flags)));
if (refs_to_fetch)
g_variant_builder_add (&builder, "{s@v}", "refs",
g_variant_new_variant (g_variant_new_strv ((const char *const*) refs_to_fetch, -1)));
return ostree_repo_pull_with_options (self, remote_name, g_variant_builder_end (&builder),
progress, cancellable, error);
}
gboolean
/* Load the summary from the cache if the provided .sig file is the same as the
cached version. */
static gboolean
_ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self,
const char *remote,
GBytes *summary_sig,
@@ -1836,7 +1812,7 @@ _ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self,
return ret;
}
gboolean
static gboolean
_ostree_repo_cache_summary (OstreeRepo *self,
const char *remote,
GBytes *summary,
@@ -1876,7 +1852,311 @@ _ostree_repo_cache_summary (OstreeRepo *self,
}
/* Documented in ostree-repo.c */
static OstreeFetcher *
_ostree_repo_remote_new_fetcher (OstreeRepo *self,
const char *remote_name,
GError **error)
{
OstreeFetcher *fetcher = NULL;
OstreeFetcherConfigFlags fetcher_flags = 0;
gboolean tls_permissive = FALSE;
gboolean success = FALSE;
g_return_val_if_fail (OSTREE_IS_REPO (self), NULL);
g_return_val_if_fail (remote_name != NULL, NULL);
if (!ostree_repo_get_remote_boolean_option (self, remote_name,
"tls-permissive", FALSE,
&tls_permissive, error))
goto out;
if (tls_permissive)
fetcher_flags |= OSTREE_FETCHER_FLAGS_TLS_PERMISSIVE;
fetcher = _ostree_fetcher_new (self->tmp_dir_fd, fetcher_flags);
{
g_autofree char *tls_client_cert_path = NULL;
g_autofree char *tls_client_key_path = NULL;
if (!ostree_repo_get_remote_option (self, remote_name,
"tls-client-cert-path", NULL,
&tls_client_cert_path, error))
goto out;
if (!ostree_repo_get_remote_option (self, remote_name,
"tls-client-key-path", NULL,
&tls_client_key_path, error))
goto out;
if ((tls_client_cert_path != NULL) != (tls_client_key_path != NULL))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Remote \"%s\" must specify both "
"\"tls-client-cert-path\" and \"tls-client-key-path\"",
remote_name);
goto out;
}
else if (tls_client_cert_path != NULL)
{
g_autoptr(GTlsCertificate) client_cert = NULL;
g_assert (tls_client_key_path != NULL);
client_cert = g_tls_certificate_new_from_files (tls_client_cert_path,
tls_client_key_path,
error);
if (client_cert == NULL)
goto out;
_ostree_fetcher_set_client_cert (fetcher, client_cert);
}
}
{
g_autofree char *tls_ca_path = NULL;
if (!ostree_repo_get_remote_option (self, remote_name,
"tls-ca-path", NULL,
&tls_ca_path, error))
goto out;
if (tls_ca_path != NULL)
{
g_autoptr(GTlsDatabase) db = NULL;
db = g_tls_file_database_new (tls_ca_path, error);
if (db == NULL)
goto out;
_ostree_fetcher_set_tls_database (fetcher, db);
}
}
{
g_autofree char *http_proxy = NULL;
if (!ostree_repo_get_remote_option (self, remote_name,
"proxy", NULL,
&http_proxy, error))
goto out;
if (http_proxy != NULL)
_ostree_fetcher_set_proxy (fetcher, http_proxy);
}
success = TRUE;
out:
if (!success)
g_clear_object (&fetcher);
return fetcher;
}
static gboolean
_ostree_preload_metadata_file (OstreeRepo *self,
OstreeFetcher *fetcher,
SoupURI *base_uri,
const char *filename,
gboolean is_metalink,
GBytes **out_bytes,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
if (is_metalink)
{
glnx_unref_object OstreeMetalink *metalink = NULL;
GError *local_error = NULL;
metalink = _ostree_metalink_new (fetcher, filename,
OSTREE_MAX_METADATA_SIZE,
base_uri);
_ostree_metalink_request_sync (metalink, NULL, out_bytes, NULL,
cancellable, &local_error);
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&local_error);
*out_bytes = NULL;
}
else if (local_error != NULL)
{
g_propagate_error (error, local_error);
goto out;
}
}
else
{
SoupURI *uri;
const char *base_path;
g_autofree char *path = NULL;
base_path = soup_uri_get_path (base_uri);
path = g_build_filename (base_path, filename, NULL);
uri = soup_uri_new_with_base (base_uri, path);
ret = _ostree_fetcher_request_uri_to_membuf (fetcher, uri,
FALSE, TRUE,
out_bytes,
OSTREE_MAX_METADATA_SIZE,
cancellable, error);
soup_uri_free (uri);
if (!ret)
goto out;
}
ret = TRUE;
out:
return ret;
}
static gboolean
repo_remote_fetch_summary (OstreeRepo *self,
const char *name,
const char *metalink_url_string,
GVariant *options,
GBytes **out_summary,
GBytes **out_signatures,
GCancellable *cancellable,
GError **error)
{
glnx_unref_object OstreeFetcher *fetcher = NULL;
g_autoptr(GMainContext) mainctx = NULL;
gboolean ret = FALSE;
SoupURI *base_uri = NULL;
gboolean from_cache = FALSE;
g_autofree char *url_override = NULL;
if (options)
(void) g_variant_lookup (options, "override-url", "&s", &url_override);
mainctx = g_main_context_new ();
g_main_context_push_thread_default (mainctx);
fetcher = _ostree_repo_remote_new_fetcher (self, name, error);
if (fetcher == NULL)
goto out;
{
g_autofree char *url_string = NULL;
if (metalink_url_string)
url_string = g_strdup (metalink_url_string);
else if (url_override)
url_string = g_strdup (url_override);
else if (!ostree_repo_remote_get_url (self, name, &url_string, error))
goto out;
base_uri = soup_uri_new (url_string);
if (base_uri == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid URL '%s'", url_string);
goto out;
}
}
if (!_ostree_preload_metadata_file (self,
fetcher,
base_uri,
"summary.sig",
metalink_url_string ? TRUE : FALSE,
out_signatures,
cancellable,
error))
goto out;
if (*out_signatures)
{
if (!_ostree_repo_load_cache_summary_if_same_sig (self,
name,
*out_signatures,
out_summary,
cancellable,
error))
goto out;
}
if (*out_summary)
from_cache = TRUE;
else
{
if (!_ostree_preload_metadata_file (self,
fetcher,
base_uri,
"summary",
metalink_url_string ? TRUE : FALSE,
out_summary,
cancellable,
error))
goto out;
}
if (!from_cache && *out_summary && *out_signatures)
{
g_autoptr(GError) temp_error = NULL;
if (!_ostree_repo_cache_summary (self,
name,
*out_summary,
*out_signatures,
cancellable,
&temp_error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
g_debug ("No permissions to save summary cache");
else
{
g_propagate_error (error, g_steal_pointer (&temp_error));
goto out;
}
}
}
ret = TRUE;
out:
if (mainctx)
g_main_context_pop_thread_default (mainctx);
if (base_uri != NULL)
soup_uri_free (base_uri);
return ret;
}
/* ------------------------------------------------------------------------------------------
* Below is the libsoup-invariant API; these should match
* the stub functions in the #else clause
* ------------------------------------------------------------------------------------------
*/
/**
* ostree_repo_pull_with_options:
* @self: Repo
* @remote_name: Name of remote
* @options: A GVariant a{sv} with an extensible set of flags.
* @progress: (allow-none): Progress
* @cancellable: Cancellable
* @error: Error
*
* Like ostree_repo_pull(), but supports an extensible set of flags.
* The following are currently defined:
*
* * refs (as): Array of string refs
* * flags (i): An instance of #OstreeRepoPullFlags
* * subdir (s): Pull just this subdirectory
* * override-remote-name (s): If local, add this remote to refspec
* * gpg-verify (b): GPG verify commits
* * gpg-verify-summary (b): GPG verify summary
* * depth (i): How far in the history to traverse; default is 0, -1 means infinite
* * disable-static-deltas (b): Do not use static deltas
* * require-static-deltas (b): Require static deltas
* * override-commit-ids (as): Array of specific commit IDs to fetch for refs
* * dry-run (b): Only print information on what will be downloaded (requires static deltas)
* * override-url (s): Fetch objects from this URL if remote specifies no metalink in options
*/
gboolean
ostree_repo_pull_with_options (OstreeRepo *self,
const char *remote_name_or_baseurl,
@@ -1889,8 +2169,6 @@ ostree_repo_pull_with_options (OstreeRepo *self,
GHashTableIter hash_iter;
gpointer key, value;
g_autoptr(GBytes) bytes_summary = NULL;
g_autofree char *remote_key = NULL;
g_autofree char *path = NULL;
g_autofree char *metalink_url_str = NULL;
g_autoptr(GHashTable) requested_refs_to_fetch = NULL;
g_autoptr(GHashTable) commits_to_fetch = NULL;
@@ -1904,13 +2182,14 @@ ostree_repo_pull_with_options (OstreeRepo *self,
guint64 end_time;
OstreeRepoPullFlags flags = 0;
const char *dir_to_pull = NULL;
char **refs_to_fetch = NULL;
g_autofree char **refs_to_fetch = NULL;
char **override_commit_ids = NULL;
GSource *update_timeout = NULL;
gboolean disable_static_deltas = FALSE;
gboolean require_static_deltas = FALSE;
gboolean opt_gpg_verify = FALSE;
gboolean opt_gpg_verify_summary = FALSE;
const char *url_override = NULL;
if (options)
{
@@ -1928,6 +2207,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
(void) g_variant_lookup (options, "require-static-deltas", "b", &require_static_deltas);
(void) g_variant_lookup (options, "override-commit-ids", "^a&s", &override_commit_ids);
(void) g_variant_lookup (options, "dry-run", "b", &pull_data->dry_run);
(void) g_variant_lookup (options, "override-url", "&s", &url_override);
}
g_return_val_if_fail (pull_data->maxdepth >= -1, FALSE);
@@ -2023,7 +2303,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
{
g_autofree char *baseurl = NULL;
if (!ostree_repo_remote_get_url (self, remote_name_or_baseurl, &baseurl, error))
if (url_override != NULL)
baseurl = g_strdup (url_override);
else if (!ostree_repo_remote_get_url (self, remote_name_or_baseurl, &baseurl, error))
goto out;
pull_data->base_uri = soup_uri_new (baseurl);
@@ -2587,3 +2869,121 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_clear_pointer (&remote_config, (GDestroyNotify) g_key_file_unref);
return ret;
}
/**
* ostree_repo_remote_fetch_summary_with_options:
* @self: Self
* @name: name of a remote
* @options: (nullable): A GVariant a{sv} with an extensible set of flags
* @out_summary: (nullable): return location for raw summary data, or %NULL
* @out_signatures: (nullable): return location for raw summary signature
* data, or %NULL
* @cancellable: a #GCancellable
* @error: a #GError
*
* Like ostree_repo_remote_fetch_summary(), but supports an extensible set of flags.
* The following are currently defined:
*
* - override-url (s): Fetch summary from this URL if remote specifies no metalink in options
*
* Returns: %TRUE on success, %FALSE on failure
*/
gboolean
ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self,
const char *name,
GVariant *options,
GBytes **out_summary,
GBytes **out_signatures,
GCancellable *cancellable,
GError **error)
{
g_autofree char *metalink_url_string = NULL;
g_autoptr(GBytes) summary = NULL;
g_autoptr(GBytes) signatures = NULL;
gboolean ret = FALSE;
gboolean gpg_verify_summary;
g_return_val_if_fail (OSTREE_REPO (self), FALSE);
g_return_val_if_fail (name != NULL, FALSE);
if (!ostree_repo_get_remote_option (self, name, "metalink", NULL,
&metalink_url_string, error))
goto out;
if (!repo_remote_fetch_summary (self,
name,
metalink_url_string,
options,
&summary,
&signatures,
cancellable,
error))
goto out;
if (!ostree_repo_remote_get_gpg_verify_summary (self, name, &gpg_verify_summary, error))
goto out;
if (gpg_verify_summary && signatures == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"GPG verification enabled, but no summary signatures found (use gpg-verify-summary=false in remote config to disable)");
goto out;
}
/* Verify any summary signatures. */
if (gpg_verify_summary && summary != NULL && signatures != NULL)
{
glnx_unref_object OstreeGpgVerifyResult *result = NULL;
result = ostree_repo_verify_summary (self,
name,
summary,
signatures,
cancellable,
error);
if (!ostree_gpg_verify_result_require_valid_signature (result, error))
goto out;
}
if (out_summary != NULL)
*out_summary = g_steal_pointer (&summary);
if (out_signatures != NULL)
*out_signatures = g_steal_pointer (&signatures);
ret = TRUE;
out:
return ret;
}
#else /* HAVE_LIBSOUP */
gboolean
ostree_repo_pull_with_options (OstreeRepo *self,
const char *remote_name,
GVariant *options,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"This version of ostree was built without libsoup, and cannot fetch over HTTP");
return FALSE;
}
gboolean
ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self,
const char *name,
GVariant *options,
GBytes **out_summary,
GBytes **out_signatures,
GCancellable *cancellable,
GError **error)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"This version of ostree was built without libsoup, and cannot fetch over HTTP");
return FALSE;
}
#endif /* HAVE_LIBSOUP */
@@ -1226,7 +1226,7 @@ get_fallback_headers (OstreeRepo *self,
*
* The @params argument should be an a{sv}. The following attributes
* are known:
* - min-fallback-size: u: Minimume uncompressed size in megabytes to use fallback, 0 to disable fallbacks
* - min-fallback-size: u: Minimum uncompressed size in megabytes to use fallback, 0 to disable fallbacks
* - max-chunk-size: u: Maximum size in megabytes of a delta part
* - max-bsdiff-size: u: Maximum size in megabytes to consider bsdiff compression
* for input files
@@ -1253,7 +1253,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
guint min_fallback_size;
guint max_bsdiff_size;
guint max_chunk_size;
GVariantBuilder metadata_builder;
g_auto(GVariantBuilder) metadata_builder = {{0,}};
DeltaOpts delta_opts = DELTAOPT_FLAG_NONE;
guint64 total_compressed_size = 0;
guint64 total_uncompressed_size = 0;
@@ -1384,16 +1384,18 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
g_autoptr(GVariant) delta_part_content = NULL;
g_autoptr(GVariant) delta_part = NULL;
g_autoptr(GVariant) delta_part_header = NULL;
GVariantBuilder *mode_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(uuu)"));
GVariantBuilder *xattr_builder = g_variant_builder_new (G_VARIANT_TYPE ("aa(ayay)"));
g_auto(GVariantBuilder) mode_builder = {{0,}};
g_auto(GVariantBuilder) xattr_builder = {{0,}};
guint8 compression_type_char;
g_variant_builder_init (&mode_builder, G_VARIANT_TYPE ("a(uuu)"));
g_variant_builder_init (&xattr_builder, G_VARIANT_TYPE ("aa(ayay)"));
{ guint j;
for (j = 0; j < part_builder->modes->len; j++)
g_variant_builder_add_value (mode_builder, part_builder->modes->pdata[j]);
g_variant_builder_add_value (&mode_builder, part_builder->modes->pdata[j]);
for (j = 0; j < part_builder->xattrs->len; j++)
g_variant_builder_add_value (xattr_builder, part_builder->xattrs->pdata[j]);
g_variant_builder_add_value (&xattr_builder, part_builder->xattrs->pdata[j]);
}
payload_b = g_string_free_to_bytes (part_builder->payload);
@@ -1403,7 +1405,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
part_builder->operations = NULL;
/* FIXME - avoid duplicating memory here */
delta_part_content = g_variant_new ("(a(uuu)aa(ayay)@ay@ay)",
mode_builder, xattr_builder,
&mode_builder, &xattr_builder,
ot_gvariant_new_ay_bytes (payload_b),
ot_gvariant_new_ay_bytes (operations_b));
g_variant_ref_sink (delta_part_content);
@@ -1481,7 +1483,8 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
descriptor_dir = g_file_get_parent (descriptor_path);
if (!gs_file_ensure_directory (descriptor_dir, TRUE, cancellable, error))
if (!glnx_shutil_mkdir_p_at (AT_FDCWD, gs_file_get_path_cached (descriptor_dir), 0755,
cancellable, error))
goto out;
for (i = 0; i < part_tempfiles->len; i++)
@@ -126,8 +126,8 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
if (g_file_info_get_file_type (file_info2) != G_FILE_TYPE_DIRECTORY)
continue;
name1 = gs_file_get_basename_cached (child);
name2 = gs_file_get_basename_cached (child2);
name1 = g_file_info_get_name (file_info);
name2 = g_file_info_get_name (file_info2);
{
g_autoptr(GFile) meta_path = g_file_get_child (child2, "superblock");
@@ -159,7 +159,8 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
}
ret = TRUE;
gs_transfer_out_value (out_deltas, &ret_deltas);
if (out_deltas)
*out_deltas = g_steal_pointer (&ret_deltas);
out:
return ret;
}
@@ -512,6 +513,7 @@ _ostree_static_delta_part_open (GInputStream *part_in,
g_bytes_get_size (inline_part_bytes) - 1);
ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
content_bytes, trusted);
g_variant_ref_sink (ret_part);
}
if (!skip_checksum)
@@ -840,7 +842,7 @@ _ostree_repo_static_delta_dump (OstreeRepo *self,
if (!ot_util_variant_map_at (self->repo_dir_fd, superblock_path,
(GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT,
TRUE, &delta_superblock, error))
OT_VARIANT_MAP_TRUSTED, &delta_superblock, error))
goto out;
g_print ("%s\n", g_variant_print (delta_superblock, 1));
+1
View File
@@ -22,6 +22,7 @@
#include "config.h"
#include "libglnx.h"
#include "ostree.h"
#include "otutil.h"
File diff suppressed because it is too large. Load diff
+48 -10
View File
@@ -115,6 +115,10 @@ gboolean ostree_repo_remote_delete (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
/**
* OstreeRepoRemoteChange:
* The remote change operation.
*/
typedef enum {
OSTREE_REPO_REMOTE_CHANGE_ADD,
OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS,
@@ -194,6 +198,15 @@ gboolean ostree_repo_remote_fetch_summary (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self,
const char *name,
GVariant *options,
GBytes **out_summary,
GBytes **out_signatures,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
OstreeRepo * ostree_repo_get_parent (OstreeRepo *self);
@@ -214,6 +227,10 @@ gboolean ostree_repo_write_config (OstreeRepo *self,
* were written to the repository in this transaction.
* @content_bytes_written: The amount of data added to the repository,
* in bytes, counting only content objects.
* @padding1: reserved
* @padding2: reserved
* @padding3: reserved
* @padding4: reserved
*
* A list of statistics for each transaction that may be
* interesting for reporting purposes.
@@ -582,7 +599,9 @@ gboolean ostree_repo_write_archive_to_mtree (OstreeRepo *
typedef struct {
guint ignore_unsupported_content : 1;
guint autocreate_parents : 1;
guint reserved : 30;
guint use_ostree_convention : 1;
guint callback_with_entry_pathname : 1;
guint reserved : 28;
guint unused_uint[8];
gpointer unused_ptrs[8];
@@ -610,7 +629,10 @@ typedef struct {
guint64 timestamp_secs;
guint unused_uint[8];
gpointer unused_ptrs[8];
char *path_prefix;
gpointer unused_ptrs[7];
} OstreeRepoExportArchiveOptions;
_OSTREE_PUBLIC
@@ -685,7 +707,8 @@ typedef enum {
OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES = 1
} OstreeRepoCheckoutOverwriteMode;
_OSTREE_PUBLIC gboolean
_OSTREE_PUBLIC
gboolean
ostree_repo_checkout_tree (OstreeRepo *self,
OstreeRepoCheckoutMode mode,
OstreeRepoCheckoutOverwriteMode overwrite_mode,
@@ -852,14 +875,16 @@ typedef enum {
OSTREE_REPO_COMMIT_TRAVERSE_FLAG_NONE = (1 << 0)
} OstreeRepoCommitTraverseFlags;
_OSTREE_PUBLIC gboolean
_OSTREE_PUBLIC
gboolean
ostree_repo_commit_traverse_iter_init_commit (OstreeRepoCommitTraverseIter *iter,
OstreeRepo *repo,
GVariant *commit,
OstreeRepoCommitTraverseFlags flags,
GError **error);
_OSTREE_PUBLIC gboolean
_OSTREE_PUBLIC
gboolean
ostree_repo_commit_traverse_iter_init_dirtree (OstreeRepoCommitTraverseIter *iter,
OstreeRepo *repo,
GVariant *dirtree,
@@ -889,8 +914,8 @@ void ostree_repo_commit_traverse_iter_get_dir (OstreeRepoCommitTraverseIter *ite
char **out_content_checksum,
char **out_meta_checksum);
_OSTREE_PUBLIC void
ostree_repo_commit_traverse_iter_clear (OstreeRepoCommitTraverseIter *iter);
_OSTREE_PUBLIC
void ostree_repo_commit_traverse_iter_clear (OstreeRepoCommitTraverseIter *iter);
_OSTREE_PUBLIC
void ostree_repo_commit_traverse_iter_cleanup (void *p);
@@ -909,7 +934,8 @@ typedef enum {
OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY
} OstreeRepoPruneFlags;
_OSTREE_PUBLIC gboolean
_OSTREE_PUBLIC
gboolean
ostree_repo_prune_static_deltas (OstreeRepo *self, const char *commit,
GCancellable *cancellable,
GError **error);
@@ -947,7 +973,8 @@ gboolean ostree_repo_pull (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC gboolean
_OSTREE_PUBLIC
gboolean
ostree_repo_pull_one_dir (OstreeRepo *self,
const char *remote_name,
const char *dir_to_pull,
@@ -986,7 +1013,8 @@ gboolean ostree_repo_sign_delta (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC gboolean
_OSTREE_PUBLIC
gboolean
ostree_repo_add_gpg_signature_summary (OstreeRepo *self,
const gchar **key_id,
const gchar *homedir,
@@ -1016,6 +1044,16 @@ OstreeGpgVerifyResult * ostree_repo_verify_commit_ext (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
OstreeGpgVerifyResult * ostree_repo_gpg_verify_data (OstreeRepo *self,
const gchar *remote_name,
GBytes *data,
GBytes *signatures,
GFile *keyringdir,
GFile *extra_keyring,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
OstreeGpgVerifyResult * ostree_repo_verify_summary (OstreeRepo *self,
const char *remote_name,
+1 -1
View File
@@ -32,7 +32,7 @@
#include "ostree-bootloader-syslinux.h"
/**
* SECTION:libostree-sepolicy
* SECTION:ostree-sepolicy
* @title: SELinux policy management
* @short_description: Read SELinux policy and manage filesystem labels
*
+2 -2
View File
@@ -32,7 +32,7 @@ _ostree_sysroot_list_deployment_dirs_for_os (GFile *osdir,
GError **error)
{
gboolean ret = FALSE;
const char *osname = gs_file_get_basename_cached (osdir);
const char *osname = glnx_basename (gs_file_get_path_cached (osdir));
g_autoptr(GFileEnumerator) dir_enum = NULL;
g_autoptr(GFile) osdeploy_dir = NULL;
GError *temp_error = NULL;
@@ -370,7 +370,7 @@ cleanup_old_deployments (OstreeSysroot *self,
g_autofree char *osname = NULL;
g_autofree char *bootcsum = NULL;
if (!parse_bootdir_name (gs_file_get_basename_cached (bootdir),
if (!parse_bootdir_name (glnx_basename (gs_file_get_path_cached (bootdir)),
&osname, &bootcsum))
g_assert_not_reached ();
+50 -38
View File
@@ -87,6 +87,39 @@ symlink_at_replace (const char *oldpath,
return ret;
}
/* Try a hardlink if we can, otherwise fall back to copying. Used
* right now for kernels/initramfs in /boot, where we can just
* hardlink if we're on the same partition.
*/
static gboolean
hardlink_or_copy_at (int src_dfd,
const char *src_subpath,
int dest_dfd,
const char *dest_subpath,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
if (linkat (src_dfd, src_subpath, dest_dfd, dest_subpath, 0) != 0)
{
if (errno == EMLINK || errno == EXDEV)
{
return glnx_file_copy_at (src_dfd, src_subpath, NULL, dest_dfd, dest_subpath, 0,
cancellable, error);
}
else
{
glnx_set_error_from_errno (error);
goto out;
}
}
ret = TRUE;
out:
return ret;
}
static gboolean
dirfd_copy_attributes_and_xattrs (int src_parent_dfd,
const char *src_name,
@@ -139,8 +172,8 @@ copy_dir_recurse (int src_parent_dfd,
GError **error)
{
gboolean ret = FALSE;
int src_dfd = -1;
int dest_dfd = -1;
glnx_fd_close int src_dfd = -1;
glnx_fd_close int dest_dfd = -1;
DIR *srcd = NULL;
struct dirent *dent;
@@ -207,10 +240,6 @@ copy_dir_recurse (int src_parent_dfd,
/* Note the srcd owns src_dfd */
src_dfd = -1;
}
if (src_dfd != -1)
(void) close (src_dfd);
if (dest_dfd != -1)
(void) close (dest_dfd);
return ret;
}
@@ -224,8 +253,8 @@ ensure_directory_from_template (int orig_etc_fd,
GError **error)
{
gboolean ret = FALSE;
int src_dfd = -1;
int target_dfd = -1;
glnx_fd_close int src_dfd = -1;
glnx_fd_close int target_dfd = -1;
g_assert (path != NULL);
g_assert (*path != '/' && *path != '\0');
@@ -283,10 +312,6 @@ ensure_directory_from_template (int orig_etc_fd,
target_dfd = -1;
}
out:
if (src_dfd != -1)
(void) close (src_dfd);
if (target_dfd != -1)
(void) close (target_dfd);
return ret;
}
@@ -308,7 +333,7 @@ copy_modified_config_file (int orig_etc_fd,
gboolean ret = FALSE;
struct stat modified_stbuf;
struct stat new_stbuf;
int dest_parent_dfd = -1;
glnx_fd_close int dest_parent_dfd = -1;
if (fstatat (modified_etc_fd, path, &modified_stbuf, AT_SYMLINK_NOFOLLOW) < 0)
{
@@ -398,8 +423,6 @@ copy_modified_config_file (int orig_etc_fd,
ret = TRUE;
out:
if (dest_parent_dfd != -1)
(void) close (dest_parent_dfd);
return ret;
}
@@ -426,9 +449,9 @@ merge_etc_changes (GFile *orig_etc,
g_autoptr(GPtrArray) removed = NULL;
g_autoptr(GPtrArray) added = NULL;
guint i;
int orig_etc_fd = -1;
int modified_etc_fd = -1;
int new_etc_fd = -1;
glnx_fd_close int orig_etc_fd = -1;
glnx_fd_close int modified_etc_fd = -1;
glnx_fd_close int new_etc_fd = -1;
modified = g_ptr_array_new_with_free_func ((GDestroyNotify) ostree_diff_item_unref);
removed = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
@@ -505,12 +528,6 @@ merge_etc_changes (GFile *orig_etc,
ret = TRUE;
out:
if (orig_etc_fd != -1)
(void) close (orig_etc_fd);
if (modified_etc_fd != -1)
(void) close (modified_etc_fd);
if (new_etc_fd != -1)
(void) close (new_etc_fd);
return ret;
}
@@ -651,7 +668,7 @@ relabel_recursively (OstreeSysroot *sysroot,
if (file_info == NULL)
break;
g_ptr_array_add (path_parts, (char*)gs_file_get_basename_cached (child));
g_ptr_array_add (path_parts, (char*)g_file_info_get_name (file_info));
ftype = g_file_info_get_file_type (file_info);
if (ftype == G_FILE_TYPE_DIRECTORY)
@@ -723,12 +740,12 @@ selinux_relabel_file (OstreeSysroot *sysroot,
goto out;
g_ptr_array_add (path_parts, (char*)prefix);
g_ptr_array_add (path_parts, (char*)gs_file_get_basename_cached (path));
g_ptr_array_add (path_parts, (char*)g_file_info_get_name (file_info));
if (!relabel_one_path (sysroot, sepolicy, path, file_info, path_parts,
cancellable, error))
{
g_prefix_error (error, "Relabeling /%s/%s: ", prefix,
gs_file_get_basename_cached (path));
g_file_info_get_name (file_info));
goto out;
}
@@ -1277,7 +1294,6 @@ install_deployment_kernel (OstreeSysroot *sysroot,
struct stat stbuf;
const char *osname = ostree_deployment_get_osname (deployment);
const char *bootcsum = ostree_deployment_get_bootcsum (deployment);
g_autoptr(GFile) bootdir = NULL;
g_autofree char *bootcsumdir = NULL;
g_autofree char *bootconfdir = NULL;
g_autofree char *bootconf_name = NULL;
@@ -1293,10 +1309,6 @@ install_deployment_kernel (OstreeSysroot *sysroot,
g_autofree char *contents = NULL;
g_autofree char *deployment_version = NULL;
g_autoptr(GHashTable) osrelease_values = NULL;
g_autofree char *linux_relpath = NULL;
g_autofree char *linux_key = NULL;
g_autofree char *initramfs_relpath = NULL;
g_autofree char *initrd_key = NULL;
g_autofree char *version_key = NULL;
g_autofree char *ostree_kernel_arg = NULL;
g_autofree char *options_key = NULL;
@@ -1342,9 +1354,9 @@ install_deployment_kernel (OstreeSysroot *sysroot,
glnx_set_prefix_error_from_errno (error, "fstat %s", dest_kernel_name);
goto out;
}
if (!glnx_file_copy_at (tree_boot_dfd, tree_kernel_name, NULL,
bootcsum_dfd, dest_kernel_name, 0,
cancellable, error))
if (!hardlink_or_copy_at (tree_boot_dfd, tree_kernel_name,
bootcsum_dfd, dest_kernel_name,
cancellable, error))
goto out;
}
@@ -1359,9 +1371,9 @@ install_deployment_kernel (OstreeSysroot *sysroot,
glnx_set_prefix_error_from_errno (error, "fstat %s", dest_initramfs_name);
goto out;
}
if (!glnx_file_copy_at (tree_boot_dfd, tree_initramfs_name, NULL,
bootcsum_dfd, dest_initramfs_name, 0,
cancellable, error))
if (!hardlink_or_copy_at (tree_boot_dfd, tree_initramfs_name,
bootcsum_dfd, dest_initramfs_name,
cancellable, error))
goto out;
}
}
+4
View File
@@ -34,6 +34,10 @@ typedef enum {
} OstreeSysrootDebugFlags;
/**
* OstreeSysroot:
* Internal struct
*/
struct OstreeSysroot {
GObject parent;
+1 -1
View File
@@ -25,7 +25,7 @@
#include "ostree-sysroot-upgrader.h"
/**
* SECTION:libostree-sysroot-upgrader
* SECTION:ostree-sysroot-upgrader
* @title: Simple upgrade class
* @short_description: Upgrade OSTree systems
*
+29 -21
View File
@@ -37,7 +37,7 @@ find_booted_deployment (OstreeSysroot *self,
GError **error);
/**
* SECTION:libostree-sysroot
* SECTION:ostree-sysroot
* @title: Root partition mount point
* @short_description: Manage physical root filesystem
*
@@ -70,10 +70,12 @@ ostree_sysroot_finalize (GObject *object)
g_clear_object (&self->path);
g_clear_object (&self->sepolicy);
g_clear_object (&self->repo);
g_clear_pointer (&self->deployments, g_ptr_array_unref);
g_clear_object (&self->booted_deployment);
glnx_release_lock_file (&self->lock);
(void) ostree_sysroot_unload (self);
ostree_sysroot_unload (self);
G_OBJECT_CLASS (ostree_sysroot_parent_class)->finalize (object);
}
@@ -276,28 +278,34 @@ ostree_sysroot_ensure_initialized (OstreeSysroot *self,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GFile) dir = NULL;
g_autoptr(GFile) ostree_dir = NULL;
g_autoptr(GFile) repo_dir = NULL;
struct stat stbuf;
ostree_dir = g_file_get_child (self->path, "ostree");
repo_dir = g_file_get_child (ostree_dir, "repo");
if (!gs_file_ensure_directory (repo_dir, TRUE, cancellable, error))
if (!ensure_sysroot_fd (self, error))
goto out;
g_clear_object (&dir);
dir = g_file_get_child (ostree_dir, "deploy");
if (!gs_file_ensure_directory (dir, TRUE, cancellable, error))
goto out;
g_clear_object (&dir);
dir = ot_gfile_get_child_build_path (ostree_dir, "repo", "objects", NULL);
if (!g_file_query_exists (dir, NULL))
{
glnx_unref_object OstreeRepo *repo = ostree_repo_new (repo_dir);
if (!ostree_repo_create (repo, OSTREE_REPO_MODE_BARE,
if (!glnx_shutil_mkdir_p_at (self->sysroot_fd, "ostree/repo", 0755,
cancellable, error))
goto out;
goto out;
if (!glnx_shutil_mkdir_p_at (self->sysroot_fd, "ostree/deploy", 0755,
cancellable, error))
goto out;
if (fstatat (self->sysroot_fd, "ostree/repo/objects", &stbuf, 0) != 0)
{
if (errno != ENOENT)
{
glnx_set_prefix_error_from_errno (error, "stat %s", "ostree/repo/objects");
goto out;
}
else
{
g_autoptr(GFile) repo_dir = g_file_resolve_relative_path (self->path, "ostree/repo");
glnx_unref_object OstreeRepo *repo = ostree_repo_new (repo_dir);
if (!ostree_repo_create (repo, OSTREE_REPO_MODE_BARE,
cancellable, error))
goto out;
}
}
ret = TRUE;
@@ -873,7 +881,7 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self,
}
g_clear_pointer (&self->deployments, g_ptr_array_unref);
g_clear_pointer (&self->booted_deployment, g_object_unref);
g_clear_object (&self->booted_deployment);
self->bootversion = -1;
self->subbootversion = -1;
+2
View File
@@ -31,3 +31,5 @@
#include <ostree-bootconfig-parser.h>
#include <ostree-diff.h>
#include <ostree-gpg-verify-result.h>
#include <ostree-autocleanups.h>
+21
View File
@@ -230,3 +230,24 @@ ot_openat_ignore_enoent (int dfd,
out:
return ret;
}
GBytes *
ot_file_mapat_bytes (int dfd,
const char *path,
GError **error)
{
glnx_fd_close int fd = openat (dfd, path, O_RDONLY | O_CLOEXEC);
g_autoptr(GMappedFile) mfile = NULL;
if (fd < 0)
{
glnx_set_error_from_errno (error);
return FALSE;
}
mfile = g_mapped_file_new_from_fd (fd, FALSE, error);
if (!mfile)
return FALSE;
return g_mapped_file_get_bytes (mfile);
}
+4
View File
@@ -66,4 +66,8 @@ gboolean ot_openat_ignore_enoent (int dfd,
int *out_fd,
GError **error);
GBytes *ot_file_mapat_bytes (int dfd,
const char *path,
GError **error);
G_END_DECLS
+11 -29
View File
@@ -254,7 +254,8 @@ ot_gfile_load_contents_utf8_allow_noent (GFile *path,
GError *temp_error = NULL;
g_autofree char *ret_contents = NULL;
ret_contents = gs_file_load_contents_utf8 (path, cancellable, &temp_error);
ret_contents = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (path), NULL,
cancellable, &temp_error);
if (!ret_contents)
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
@@ -356,8 +357,8 @@ ot_gfile_replace_contents_fsync (GFile *path,
GError **error)
{
gboolean ret = FALSE;
int parent_dfd;
const char *target_basename = gs_file_get_basename_cached (path);
glnx_fd_close int parent_dfd = -1;
const char *target_basename = glnx_basename (gs_file_get_path_cached (path));
g_autoptr(GFile) parent = NULL;
parent = g_file_get_parent (path);
@@ -373,8 +374,6 @@ ot_gfile_replace_contents_fsync (GFile *path,
ret = TRUE;
out:
if (parent_dfd != -1)
(void) close (parent_dfd);
return ret;
}
@@ -389,25 +388,12 @@ ot_gfile_ensure_unlinked (GFile *path,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GError *temp_error = NULL;
if (!gs_file_unlink (path, cancellable, &temp_error))
if (unlink (gs_file_get_path_cached (path)) != 0)
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&temp_error);
}
else
{
g_propagate_error (error, temp_error);
goto out;
}
if (errno != ENOENT)
return FALSE;
}
ret = TRUE;
out:
return ret;
return TRUE;
}
/**
@@ -424,7 +410,7 @@ ot_util_fsync_directory (GFile *dir,
GError **error)
{
gboolean ret = FALSE;
int dfd = -1;
glnx_fd_close int dfd = -1;
if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (dir), TRUE,
&dfd, error))
@@ -438,8 +424,6 @@ ot_util_fsync_directory (GFile *dir,
ret = TRUE;
out:
if (dfd != -1)
(void) close (dfd);
return ret;
}
@@ -458,8 +442,8 @@ ot_util_ensure_directory_and_fsync (GFile *dir,
GError **error)
{
gboolean ret = FALSE;
int parentfd = -1;
const char *basename = gs_file_get_basename_cached (dir);
glnx_fd_close int parentfd = -1;
const char *basename = glnx_basename (gs_file_get_path_cached (dir));
g_autoptr(GFile) parent = g_file_get_parent (dir);
again:
@@ -507,7 +491,5 @@ ot_util_ensure_directory_and_fsync (GFile *dir,
ret = TRUE;
out:
if (parentfd != -1)
(void) close (parentfd);
return ret;
}
+20 -48
View File
@@ -33,7 +33,10 @@
GVariant *
ot_gvariant_new_empty_string_dict (void)
{
return g_variant_builder_end (g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")));
g_auto(GVariantBuilder) builder = {{0,}};
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
return g_variant_builder_end (&builder);
}
GVariant *
@@ -114,63 +117,31 @@ ot_util_variant_take_ref (GVariant *variant)
return g_variant_take_ref (variant);
}
/**
* ot_util_variant_map:
* @src: a #GFile
* @type: Use this for variant
* @trusted: See documentation of g_variant_new_from_data()
* @out_variant: (out): Return location for new variant
* @error:
*
* Memory-map @src, and store a new #GVariant referring to this memory
* in @out_variant. Note the returned @out_variant is not floating.
*/
gboolean
ot_util_variant_map (GFile *src,
const GVariantType *type,
gboolean trusted,
GVariant **out_variant,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GVariant) ret_variant = NULL;
GMappedFile *mfile = NULL;
mfile = gs_file_map_noatime (src, NULL, error);
if (!mfile)
goto out;
ret_variant = g_variant_new_from_data (type,
g_mapped_file_get_contents (mfile),
g_mapped_file_get_length (mfile),
trusted,
(GDestroyNotify) g_mapped_file_unref,
mfile);
g_variant_ref_sink (ret_variant);
ret = TRUE;
ot_transfer_out_value(out_variant, &ret_variant);
out:
return ret;
}
gboolean
ot_util_variant_map_at (int dfd,
const char *path,
const GVariantType *type,
gboolean trusted,
OtVariantMapFlags flags,
GVariant **out_variant,
GError **error)
{
glnx_fd_close int fd = -1;
g_autoptr(GVariant) ret_variant = NULL;
const gboolean trusted = (flags & OT_VARIANT_MAP_TRUSTED) > 0;
fd = openat (dfd, path, O_RDONLY | O_CLOEXEC);
if (fd < 0)
{
glnx_set_error_from_errno (error);
g_prefix_error (error, "Opening %s: ", path);
return FALSE;
if (errno == ENOENT && (flags & OT_VARIANT_MAP_ALLOW_NOENT) > 0)
{
*out_variant = NULL;
return TRUE;
}
else
{
glnx_set_error_from_errno (error);
g_prefix_error (error, "Opening %s: ", path);
return FALSE;
}
}
return ot_util_variant_map_fd (fd, 0, type, trusted, out_variant, error);
@@ -186,6 +157,7 @@ variant_map_data_destroy (gpointer data)
{
VariantMapData *mdata = data;
(void) munmap (mdata->addr, mdata->len);
g_free (mdata);
}
gboolean
@@ -221,8 +193,8 @@ ot_util_variant_map_fd (int fd,
mdata->len = len;
ret = TRUE;
*out_variant = g_variant_new_from_data (type, map, len, trusted,
variant_map_data_destroy, mdata);
*out_variant = g_variant_ref_sink (g_variant_new_from_data (type, map, len, trusted,
variant_map_data_destroy, mdata));
out:
return ret;
}
+5 -6
View File
@@ -42,16 +42,15 @@ gboolean ot_util_variant_save (GFile *dest,
GCancellable *cancellable,
GError **error);
gboolean ot_util_variant_map (GFile *src,
const GVariantType *type,
gboolean trusted,
GVariant **out_variant,
GError **error);
typedef enum {
OT_VARIANT_MAP_TRUSTED = (1 << 0),
OT_VARIANT_MAP_ALLOW_NOENT = (1 << 1)
} OtVariantMapFlags;
gboolean ot_util_variant_map_at (int dfd,
const char *path,
const GVariantType *type,
gboolean trusted,
OtVariantMapFlags flags,
GVariant **out_variant,
GError **error);
+18 -24
View File
@@ -39,8 +39,7 @@ ot_admin_builtin_init_fs (int argc, char **argv, GCancellable *cancellable, GErr
GOptionContext *context;
glnx_unref_object OstreeSysroot *sysroot = NULL;
gboolean ret = FALSE;
g_autoptr(GFile) dir = NULL;
g_autoptr(GFile) child = NULL;
glnx_fd_close int root_dfd = -1;
glnx_unref_object OstreeSysroot *target_sysroot = NULL;
guint i;
const char *normal_toplevels[] = {"boot", "dev", "home", "proc", "run", "sys"};
@@ -58,36 +57,31 @@ ot_admin_builtin_init_fs (int argc, char **argv, GCancellable *cancellable, GErr
goto out;
}
dir = g_file_new_for_path (argv[1]);
target_sysroot = ostree_sysroot_new (dir);
if (!glnx_opendirat (AT_FDCWD, argv[1], TRUE, &root_dfd, error))
goto out;
{ g_autoptr(GFile) dir = g_file_new_for_path (argv[1]);
target_sysroot = ostree_sysroot_new (dir);
}
for (i = 0; i < G_N_ELEMENTS(normal_toplevels); i++)
{
child = g_file_get_child (dir, normal_toplevels[i]);
if (!gs_file_ensure_directory_mode (child, 0755, cancellable, error))
if (!glnx_shutil_mkdir_p_at (root_dfd, normal_toplevels[i], 0755,
cancellable, error))
goto out;
g_clear_object (&child);
}
child = g_file_get_child (dir, "root");
if (!gs_file_ensure_directory_mode (child, 0700, cancellable, error))
if (!glnx_shutil_mkdir_p_at (root_dfd, "root", 0700,
cancellable, error))
goto out;
g_clear_object (&child);
child = g_file_get_child (dir, "tmp");
if (!gs_file_ensure_directory_mode (child, 01777, cancellable, error))
if (!glnx_shutil_mkdir_p_at (root_dfd, "tmp", 01777,
cancellable, error))
goto out;
/* FIXME - we should be using an API that explicitly ignores umask;
*/
{
const char *path = gs_file_get_path_cached (child);
if (chmod (path, 01777) == -1)
{
gs_set_prefix_error_from_errno (error, errno, "chmod");
goto out;
}
}
g_clear_object (&child);
if (fchmodat (root_dfd, "tmp", 01777, 0) == -1)
{
glnx_set_prefix_error_from_errno (error, "chmod: %s", "tmp");
goto out;
}
if (!ostree_sysroot_ensure_initialized (target_sysroot, cancellable, error))
goto out;
+1 -1
View File
@@ -20,11 +20,11 @@
#include "config.h"
#include "ot-main.h"
#include "ot-builtins.h"
#include "ot-admin-instutil-builtins.h"
#include "ot-admin-builtins.h"
#include "ot-admin-functions.h"
#include "ot-main.h"
#include "ostree.h"
#include <glib/gi18n.h>
+16 -24
View File
@@ -61,8 +61,6 @@ ot_admin_builtin_switch (int argc, char **argv, GCancellable *cancellable, GErro
glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
glnx_unref_object OstreeAsyncProgress *progress = NULL;
gboolean changed;
GSConsole *console = NULL;
gboolean in_status_line = FALSE;
GKeyFile *old_origin;
GKeyFile *new_origin = NULL;
@@ -125,28 +123,24 @@ ot_admin_builtin_switch (int argc, char **argv, GCancellable *cancellable, GErro
if (!ostree_sysroot_upgrader_set_origin (upgrader, new_origin, cancellable, error))
goto out;
console = gs_console_get ();
if (console)
{
gs_console_begin_status_line (console, "", NULL, NULL);
in_status_line = TRUE;
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
}
{ g_auto(GLnxConsoleRef) console = { 0, };
glnx_console_lock (&console);
/* Always allow older...there's not going to be a chronological
* relationship necessarily.
*/
if (!ostree_sysroot_upgrader_pull (upgrader, 0,
OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER,
progress, &changed,
cancellable, error))
goto out;
if (console.is_tty)
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
if (in_status_line)
{
gs_console_end_status_line (console, NULL, NULL);
in_status_line = FALSE;
}
/* Always allow older...there's not going to be a chronological
* relationship necessarily.
*/
if (!ostree_sysroot_upgrader_pull (upgrader, 0,
OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER,
progress, &changed,
cancellable, error))
goto out;
if (progress)
ostree_async_progress_finish (progress);
}
if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
goto out;
@@ -171,8 +165,6 @@ ot_admin_builtin_switch (int argc, char **argv, GCancellable *cancellable, GErro
ret = TRUE;
out:
if (in_status_line)
gs_console_end_status_line (console, NULL, NULL);
if (new_origin)
g_key_file_unref (new_origin);
if (context)
+14 -22
View File
@@ -55,8 +55,6 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr
g_autoptr(GFile) deployment_path = NULL;
g_autoptr(GFile) deployment_origin_path = NULL;
g_autoptr(GKeyFile) origin = NULL;
GSConsole *console = NULL;
gboolean in_status_line = FALSE;
glnx_unref_object OstreeAsyncProgress *progress = NULL;
gboolean changed;
OstreeSysrootUpgraderPullFlags upgraderpullflags = 0;
@@ -108,27 +106,23 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr
}
}
console = gs_console_get ();
if (console)
{
gs_console_begin_status_line (console, "", NULL, NULL);
in_status_line = TRUE;
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
}
{ g_auto(GLnxConsoleRef) console = { 0, };
glnx_console_lock (&console);
if (opt_allow_downgrade)
upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;
if (console.is_tty)
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgraderpullflags,
progress, &changed,
cancellable, error))
goto out;
if (opt_allow_downgrade)
upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;
if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgraderpullflags,
progress, &changed,
cancellable, error))
goto out;
if (in_status_line)
{
gs_console_end_status_line (console, NULL, NULL);
in_status_line = FALSE;
}
if (progress)
ostree_async_progress_finish (progress);
}
if (!changed)
{
@@ -148,8 +142,6 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr
ret = TRUE;
out:
if (in_status_line)
gs_console_end_status_line (console, NULL, NULL);
if (context)
g_option_context_free (context);
return ret;
+1
View File
@@ -22,6 +22,7 @@
#include "config.h"
#include "libglnx.h"
#include "ot-admin-functions.h"
#include "otutil.h"
#include "ostree.h"
@@ -120,7 +120,7 @@ relabel_recursively (OstreeSePolicy *sepolicy,
if (file_info == NULL)
break;
g_ptr_array_add (path_parts, (char*)gs_file_get_basename_cached (child));
g_ptr_array_add (path_parts, (char*)g_file_info_get_name (file_info));
ftype = g_file_info_get_file_type (file_info);
if (ftype == G_FILE_TYPE_DIRECTORY)
+1 -1
View File
@@ -22,10 +22,10 @@
#include "config.h"
#include "ot-main.h"
#include "ot-builtins.h"
#include "ot-admin-builtins.h"
#include "ot-admin-functions.h"
#include "ot-main.h"
#include "ostree.h"
#include "ostree-repo-file.h"
+111 -52
View File
@@ -32,10 +32,12 @@
static char *opt_subject;
static char *opt_body;
static gboolean opt_editor;
static char *opt_parent;
static gboolean opt_orphan;
static char *opt_branch;
static char *opt_statoverride_file;
static char *opt_skiplist_file;
static char **opt_metadata_strings;
static char **opt_detached_metadata_strings;
static gboolean opt_link_checkout_speedup;
@@ -72,6 +74,7 @@ static GOptionEntry options[] = {
{ "parent", 0, 0, G_OPTION_ARG_STRING, &opt_parent, "Parent ref, or \"none\"", "REF" },
{ "subject", 's', 0, G_OPTION_ARG_STRING, &opt_subject, "One line subject", "SUBJECT" },
{ "body", 'm', 0, G_OPTION_ARG_STRING, &opt_body, "Full description", "BODY" },
{ "editor", 'e', 0, G_OPTION_ARG_NONE, &opt_editor, "Use an editor to write the commit message", NULL },
{ "branch", 'b', 0, G_OPTION_ARG_STRING, &opt_branch, "Branch", "BRANCH" },
{ "orphan", 0, 0, G_OPTION_ARG_NONE, &opt_orphan, "Create a commit without writing a ref", NULL },
{ "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_trees, "Overlay the given argument as a tree", "dir=PATH or tar=TARFILE or ref=COMMIT" },
@@ -84,6 +87,7 @@ static GOptionEntry options[] = {
{ "tar-autocreate-parents", 0, 0, G_OPTION_ARG_NONE, &opt_tar_autocreate_parents, "When loading tar archives, automatically create parent directories as needed", NULL },
{ "skip-if-unchanged", 0, 0, G_OPTION_ARG_NONE, &opt_skip_if_unchanged, "If the contents are unchanged from previous commit, do nothing", NULL },
{ "statoverride", 0, 0, G_OPTION_ARG_FILENAME, &opt_statoverride_file, "File containing list of modifications to make to permissions", "PATH" },
{ "skip-list", 0, 0, G_OPTION_ARG_FILENAME, &opt_skiplist_file, "File containing list of files to skip", "PATH" },
{ "table-output", 0, 0, G_OPTION_ARG_NONE, &opt_table_output, "Output more information in a KEY: VALUE format", NULL },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the commit with", "KEY-ID"},
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"},
@@ -95,65 +99,85 @@ static GOptionEntry options[] = {
};
static gboolean
parse_statoverride_file (GHashTable **out_mode_add,
GCancellable *cancellable,
GError **error)
parse_file_by_line (const char *path,
gboolean (*cb)(const char*, void*, GError**),
void *cbdata,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gsize len;
char **iter = NULL; /* nofree */
g_autoptr(GHashTable) ret_hash = NULL;
g_autoptr(GFile) path = NULL;
g_autofree char *contents = NULL;
g_autoptr(GFile) file = NULL;
char **lines = NULL;
path = g_file_new_for_path (opt_statoverride_file);
if (!g_file_load_contents (path, cancellable, &contents, &len, NULL,
error))
file = g_file_new_for_path (path);
if (!g_file_load_contents (file, cancellable, &contents, NULL, NULL, error))
goto out;
ret_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
lines = g_strsplit (contents, "\n", -1);
for (iter = lines; iter && *iter; iter++)
for (char **iter = lines; iter && *iter; iter++)
{
const char *line = *iter;
/* skip empty lines at least */
if (**iter == '\0')
continue;
if (*line == '+')
{
const char *spc;
guint mode_add;
spc = strchr (line + 1, ' ');
if (!spc)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Malformed statoverride file");
goto out;
}
mode_add = (guint32)(gint32)g_ascii_strtod (line + 1, NULL);
g_hash_table_insert (ret_hash,
g_strdup (spc + 1),
GUINT_TO_POINTER((gint32)mode_add));
}
if (!cb (*iter, cbdata, error))
goto out;
}
ret = TRUE;
ot_transfer_out_value (out_mode_add, &ret_hash);
out:
out:
g_strfreev (lines);
return ret;
}
static gboolean
handle_statoverride_line (const char *line,
void *data,
GError **error)
{
GHashTable *files = data;
const char *spc;
guint mode_add;
spc = strchr (line, ' ');
if (spc == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Malformed statoverride file (no space found)");
return FALSE;
}
mode_add = (guint32)(gint32)g_ascii_strtod (line, NULL);
g_hash_table_insert (files, g_strdup (spc + 1),
GUINT_TO_POINTER((gint32)mode_add));
return TRUE;
}
static gboolean
handle_skiplist_line (const char *line,
void *data,
GError **error)
{
GHashTable *files = data;
g_hash_table_add (files, g_strdup (line));
return TRUE;
}
struct CommitFilterData {
GHashTable *mode_adds;
GHashTable *skip_list;
};
static OstreeRepoCommitFilterResult
commit_filter (OstreeRepo *self,
const char *path,
GFileInfo *file_info,
gpointer user_data)
{
GHashTable *mode_adds = user_data;
struct CommitFilterData *data = user_data;
GHashTable *mode_adds = data->mode_adds;
GHashTable *skip_list = data->skip_list;
gpointer value;
if (opt_owner_uid >= 0)
@@ -169,7 +193,13 @@ commit_filter (OstreeRepo *self,
current_mode | mode_add);
g_hash_table_remove (mode_adds, path);
}
if (skip_list && g_hash_table_contains (skip_list, path))
{
g_hash_table_remove (skip_list, path);
return OSTREE_REPO_COMMIT_FILTER_SKIP;
}
return OSTREE_REPO_COMMIT_FILTER_ALLOW;
}
@@ -188,14 +218,18 @@ commit_editor (OstreeRepo *repo,
char **lines = NULL;
int i;
*subject = NULL;
*body = NULL;
input = g_strdup_printf ("\n"
"# Please enter the commit message for your changes. The first line will\n"
"# become the subject, and the remainder the body. Lines starting\n"
"# with '#' will be ignored, and an empty message aborts the commit."
"%s%s\n", branch ? "\n#\n# Branch: " : "", branch ?: "");
"%s%s%s%s%s%s\n"
, branch ? "\n#\n# Branch: " : "", branch ? branch : ""
, *subject ? "\n" : "", *subject ? *subject : ""
, *body ? "\n" : "", *body ? *body : ""
);
*subject = NULL;
*body = NULL;
output = ot_editor_prompt (repo, input, cancellable, error);
if (output == NULL)
@@ -310,9 +344,11 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
glnx_unref_object OstreeMutableTree *mtree = NULL;
g_autofree char *tree_type = NULL;
g_autoptr(GHashTable) mode_adds = NULL;
g_autoptr(GHashTable) skip_list = NULL;
OstreeRepoCommitModifierFlags flags = 0;
OstreeRepoCommitModifier *modifier = NULL;
OstreeRepoTransactionStats stats;
struct CommitFilterData filter_data = { 0, };
context = g_option_context_new ("[PATH] - Commit a new revision");
@@ -324,7 +360,17 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
if (opt_statoverride_file)
{
if (!parse_statoverride_file (&mode_adds, cancellable, error))
mode_adds = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
if (!parse_file_by_line (opt_statoverride_file, handle_statoverride_line,
mode_adds, cancellable, error))
goto out;
}
if (opt_skiplist_file)
{
skip_list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
if (!parse_file_by_line (opt_skiplist_file, handle_skiplist_line,
skip_list, cancellable, error))
goto out;
}
@@ -359,9 +405,13 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
|| opt_owner_uid >= 0
|| opt_owner_gid >= 0
|| opt_statoverride_file != NULL
|| opt_skiplist_file != NULL
|| opt_no_xattrs)
{
modifier = ostree_repo_commit_modifier_new (flags, commit_filter, mode_adds, NULL);
filter_data.mode_adds = mode_adds;
filter_data.skip_list = skip_list;
modifier = ostree_repo_commit_modifier_new (flags, commit_filter,
&filter_data, NULL);
}
if (opt_parent)
@@ -381,19 +431,12 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
goto out;
}
if (!opt_subject && !opt_body)
if (opt_editor)
{
if (!commit_editor (repo, opt_branch, &opt_subject, &opt_body, cancellable, error))
goto out;
}
if (!opt_subject)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"A subject must be specified with --subject");
goto out;
}
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
goto out;
@@ -491,6 +534,22 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
goto out;
}
if (skip_list && g_hash_table_size (skip_list) > 0)
{
GHashTableIter hash_iter;
gpointer key;
g_hash_table_iter_init (&hash_iter, skip_list);
while (g_hash_table_iter_next (&hash_iter, &key, NULL))
{
g_printerr ("Unmatched skip-list path: %s\n", (char*)key);
}
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Unmatched skip-list paths");
goto out;
}
if (!ostree_repo_write_mtree (repo, mtree, &root, cancellable, error))
goto out;
+13 -1
View File
@@ -32,10 +32,14 @@
#endif
static char *opt_output_path;
static char *opt_subpath;
static char *opt_prefix;
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 },
{ "subpath", 0, 0, G_OPTION_ARG_STRING, &opt_subpath, "Checkout sub-directory PATH", "PATH" },
{ "prefix", 0, 0, G_OPTION_ARG_STRING, &opt_prefix, "Add PATH as prefix to archive pathnames", "PATH" },
{ "output", 'o', 0, G_OPTION_ARG_STRING, &opt_output_path, "Output to PATH ", "PATH" },
{ NULL }
};
@@ -60,6 +64,7 @@ ostree_builtin_export (int argc, char **argv, GCancellable *cancellable, GError
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;
@@ -124,7 +129,14 @@ ostree_builtin_export (int argc, char **argv, GCancellable *cancellable, GError
opts.timestamp_secs = ostree_commit_get_timestamp (commit_data);
if (!ostree_repo_export_tree_to_archive (repo, &opts, (OstreeRepoFile*)root, a,
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;
+1 -1
View File
@@ -37,7 +37,7 @@ gboolean
ostree_builtin_init (int argc, char **argv, GCancellable *cancellable, GError **error)
{
GOptionContext *context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
gboolean ret = FALSE;
OstreeRepoMode mode;
+10 -10
View File
@@ -55,7 +55,6 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr
glnx_unref_object OstreeRepo *repo = NULL;
int i;
const char *src_repo_arg;
GSConsole *console = NULL;
g_autofree char *src_repo_uri = NULL;
glnx_unref_object OstreeAsyncProgress *progress = NULL;
g_autoptr(GPtrArray) refs_to_fetch = NULL;
@@ -132,14 +131,11 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr
g_ptr_array_add (refs_to_fetch, NULL);
}
console = gs_console_get ();
if (console)
{
gs_console_begin_status_line (console, "", NULL, NULL);
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
}
{ GVariantBuilder builder;
g_auto(GLnxConsoleRef) console = { 0, };
glnx_console_lock (&console);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&builder, "{s@v}", "flags",
@@ -158,17 +154,21 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr
g_variant_builder_add (&builder, "{s@v}", "depth",
g_variant_new_variant (g_variant_new_int32 (opt_depth)));
if (console.is_tty)
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
if (!ostree_repo_pull_with_options (repo, src_repo_uri,
g_variant_builder_end (&builder),
progress,
cancellable, error))
goto out;
if (progress)
ostree_async_progress_finish (progress);
}
ret = TRUE;
out:
if (progress)
ostree_async_progress_finish (progress);
if (context)
g_option_context_free (context);
if (repo)
+38 -37
View File
@@ -37,7 +37,8 @@ static gboolean opt_untrusted;
static char* opt_subpath;
static char* opt_cache_dir;
static int opt_depth = 0;
static char* opt_url;
static GOptionEntry options[] = {
{ "commit-metadata-only", 0, 0, G_OPTION_ARG_NONE, &opt_commit_only, "Fetch only the commit metadata", NULL },
{ "cache-dir", 0, 0, G_OPTION_ARG_STRING, &opt_cache_dir, "Use custom cache dir", NULL },
@@ -49,6 +50,7 @@ static GOptionEntry options[] = {
{ "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not trust (local) sources", NULL },
{ "dry-run", 0, 0, G_OPTION_ARG_NONE, &opt_dry_run, "Only print information on what will be downloaded (requires static deltas)", NULL },
{ "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Traverse DEPTH parents (-1=infinite) (default: 0)", "DEPTH" },
{ "url", 0, 0, G_OPTION_ARG_STRING, &opt_url, "Pull objects from this URL instead of the one from the remote config", NULL },
{ NULL }
};
@@ -56,16 +58,17 @@ static void
gpg_verify_result_cb (OstreeRepo *repo,
const char *checksum,
OstreeGpgVerifyResult *result,
GSConsole *console)
GLnxConsoleRef *console)
{
/* Temporarily place the GSConsole stream (which is just stdout)
* back in normal mode before printing GPG verification results. */
gs_console_end_status_line (console, NULL, NULL);
/* Temporarily place the tty back in normal mode before printing GPG
* verification results.
*/
glnx_console_unlock (console);
g_print ("\n");
ostree_print_gpg_verify_result (result);
gs_console_begin_status_line (console, "", NULL, NULL);
glnx_console_lock (console);
}
static gboolean printed_console_progress;
@@ -109,7 +112,6 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError **
gboolean ret = FALSE;
g_autofree char *remote = NULL;
OstreeRepoPullFlags pullflags = 0;
GSConsole *console = NULL;
g_autoptr(GPtrArray) refs_to_fetch = NULL;
g_autoptr(GPtrArray) override_commit_ids = NULL;
glnx_unref_object OstreeAsyncProgress *progress = NULL;
@@ -204,30 +206,16 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError **
g_ptr_array_add (refs_to_fetch, NULL);
}
if (!opt_dry_run)
{
console = gs_console_get ();
if (console)
{
gs_console_begin_status_line (console, "", NULL, NULL);
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
signal_handler_id = g_signal_connect (repo, "gpg-verify-result",
G_CALLBACK (gpg_verify_result_cb),
console);
}
}
else
{
progress = ostree_async_progress_new_and_connect (dry_run_console_progress_changed, console);
signal_handler_id = g_signal_connect (repo, "gpg-verify-result",
G_CALLBACK (gpg_verify_result_cb),
console);
}
{
GVariantBuilder builder;
g_auto(GLnxConsoleRef) console = { 0, };
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
glnx_console_lock (&console);
if (opt_url)
g_variant_builder_add (&builder, "{s@v}", "override-url",
g_variant_new_variant (g_variant_new_string (opt_url)));
if (opt_subpath)
g_variant_builder_add (&builder, "{s@v}", "subdir",
g_variant_new_variant (g_variant_new_string (opt_subpath)));
@@ -252,25 +240,38 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError **
g_variant_builder_add (&builder, "{s@v}", "override-commit-ids",
g_variant_new_variant (g_variant_new_strv ((const char*const*)override_commit_ids->pdata, override_commit_ids->len)));
if (!opt_dry_run)
{
if (console.is_tty)
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
}
else
{
progress = ostree_async_progress_new_and_connect (dry_run_console_progress_changed, NULL);
}
if (console.is_tty)
{
signal_handler_id = g_signal_connect (repo, "gpg-verify-result",
G_CALLBACK (gpg_verify_result_cb),
&console);
}
if (!ostree_repo_pull_with_options (repo, remote, g_variant_builder_end (&builder),
progress, cancellable, error))
goto out;
if (progress)
ostree_async_progress_finish (progress);
if (opt_dry_run)
g_assert (printed_console_progress);
}
if (progress)
ostree_async_progress_finish (progress);
if (opt_dry_run)
g_assert (printed_console_progress);
ret = TRUE;
out:
if (signal_handler_id > 0)
g_signal_handler_disconnect (repo, signal_handler_id);
if (console)
gs_console_end_status_line (console, NULL, NULL);
if (context)
g_option_context_free (context);
return ret;
+45 -1
View File
@@ -28,10 +28,12 @@
static gboolean opt_delete;
static gboolean opt_list;
static char *opt_create;
static GOptionEntry options[] = {
{ "delete", 0, 0, G_OPTION_ARG_NONE, &opt_delete, "Delete refs which match PREFIX, rather than listing them", NULL },
{ "list", 0, 0, G_OPTION_ARG_NONE, &opt_list, "Do not remove the prefix from the refs", NULL },
{ "create", 0, 0, G_OPTION_ARG_STRING, &opt_create, "Create a new ref for an existing commit", "NEWREF" },
{ NULL }
};
@@ -48,10 +50,16 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
cancellable, error))
goto out;
}
else if (opt_create)
{
if (!ostree_repo_list_refs_ext (repo, NULL, &refs, OSTREE_REPO_LIST_REFS_EXT_NONE,
cancellable, error))
goto out;
}
else if (!ostree_repo_list_refs (repo, refspec_prefix, &refs, cancellable, error))
goto out;
if (!opt_delete)
if (!opt_delete && !opt_create)
{
g_hash_table_iter_init (&hashiter, refs);
while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
@@ -60,7 +68,30 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
g_print ("%s\n", ref);
}
}
else if (opt_create)
{
g_autofree char *checksum = NULL;
g_autofree char *checksum_existing = NULL;
if (!ostree_repo_resolve_rev (repo, opt_create, TRUE, &checksum_existing, error))
goto out;
if (checksum_existing != NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"--create specified but ref %s already exists", opt_create);
goto out;
}
if (!ostree_repo_resolve_rev (repo, refspec_prefix, FALSE, &checksum, error))
goto out;
if (!ostree_repo_set_ref_immediate (repo, NULL, opt_create, checksum,
cancellable, error))
goto out;
}
else
/* delete */
{
g_hash_table_iter_init (&hashiter, refs);
while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
@@ -97,6 +128,12 @@ ostree_builtin_refs (int argc, char **argv, GCancellable *cancellable, GError **
if (argc >= 2)
{
if (opt_create && argc > 2)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"You must specify only 1 existing ref when creating a new ref");
goto out;
}
for (i = 1; i < argc; i++)
if (!do_ref (repo, argv[i], cancellable, error))
goto out;
@@ -110,6 +147,13 @@ ostree_builtin_refs (int argc, char **argv, GCancellable *cancellable, GError **
"At least one PREFIX is required when deleting refs");
goto out;
}
else if (opt_create)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"You must specify an existing ref when creating a new ref");
goto out;
}
ret = do_ref (repo, NULL, cancellable, error);
}
+1 -4
View File
@@ -51,12 +51,9 @@ do_print_variant_generic (const GVariantType *type,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GFile) f = NULL;
g_autoptr(GVariant) variant = NULL;
f = g_file_new_for_path (filename);
if (!ot_util_variant_map (f, type, TRUE, &variant, error))
if (!ot_util_variant_map_at (AT_FDCWD, filename, type, TRUE, &variant, error))
goto out;
ot_dump_variant (variant);
+1 -1
View File
@@ -31,7 +31,7 @@ static char *opt_gpg_homedir;
static GOptionEntry options[] = {
{ "update", 'u', 0, G_OPTION_ARG_NONE, &opt_update, "Update the summary", NULL },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the commit with", "KEY-ID"},
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the summary with", "KEY-ID"},
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"},
{ NULL }
};
+74 -5
View File
@@ -22,6 +22,8 @@
#include <libsoup/soup.h>
#include <gio/gunixoutputstream.h>
#include "ot-main.h"
#include "ot-builtins.h"
#include "ostree.h"
@@ -32,6 +34,7 @@
#include <signal.h>
static char *opt_port_file = NULL;
static char *opt_log = NULL;
static gboolean opt_daemonize;
static gboolean opt_autoexit;
static gboolean opt_force_ranges;
@@ -40,6 +43,7 @@ static gint opt_port = 0;
typedef struct {
GFile *root;
gboolean running;
GOutputStream *log;
} OtTrivialHttpd;
static GOptionEntry options[] = {
@@ -48,9 +52,31 @@ static GOptionEntry options[] = {
{ "port", 'P', 0, G_OPTION_ARG_INT, &opt_port, "Use the specified TCP port", NULL },
{ "port-file", 'p', 0, G_OPTION_ARG_FILENAME, &opt_port_file, "Write port number to PATH (- for standard output)", "PATH" },
{ "force-range-requests", 0, 0, G_OPTION_ARG_NONE, &opt_force_ranges, "Force range requests by only serving half of files", NULL },
{ "log-file", 0, 0, G_OPTION_ARG_FILENAME, &opt_log, "Put logs here", "PATH" },
{ NULL }
};
static void
httpd_log (OtTrivialHttpd *httpd, const gchar *format, ...) __attribute__ ((format(printf, 2, 3)));
static void
httpd_log (OtTrivialHttpd *httpd, const gchar *format, ...)
{
g_autoptr(GString) str = NULL;
va_list args;
gsize written;
if (!httpd->log)
return;
str = g_string_new (NULL);
va_start (args, format);
g_string_vprintf (str, format, args);
va_end (args);
g_output_stream_write_all (httpd->log, str->str, str->len, &written, NULL, NULL);
}
static int
compare_strings (gconstpointer a, gconstpointer b)
{
@@ -154,6 +180,7 @@ do_get (OtTrivialHttpd *self,
struct stat stbuf;
g_autofree char *safepath = NULL;
httpd_log (self, "serving %s\n", path);
if (strstr (path, "../") != NULL)
{
soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
@@ -296,6 +323,16 @@ do_get (OtTrivialHttpd *self,
soup_message_set_status (msg, SOUP_STATUS_OK);
}
out:
{
guint status = 0;
g_autofree gchar *reason = NULL;
g_object_get (msg,
"status-code", &status,
"reason-phrase", &reason,
NULL);
httpd_log (self, " status: %s (%u)\n", reason, status);
}
return;
}
@@ -305,9 +342,6 @@ httpd_callback (SoupServer *server, SoupMessage *msg,
SoupClientContext *context, gpointer data)
{
OtTrivialHttpd *self = data;
SoupMessageHeadersIter iter;
soup_message_headers_iter_init (&iter, msg->request_headers);
if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD)
do_get (self, server, msg, path, context);
@@ -354,6 +388,37 @@ ostree_builtin_trivial_httpd (int argc, char **argv, GCancellable *cancellable,
app->root = g_file_new_for_path (dirpath);
if (opt_log)
{
GOutputStream *stream = NULL;
if (g_strcmp0 (opt_log, "-") == 0)
{
if (opt_daemonize)
{
ot_util_usage_error (context, "Cannot use --log-file=- and --daemonize at the same time", error);
goto out;
}
stream = G_OUTPUT_STREAM (g_unix_output_stream_new (STDOUT_FILENO, FALSE));
}
else
{
g_autoptr(GFile) log_file;
GFileOutputStream* log_stream;
log_file = g_file_new_for_path (opt_log);
log_stream = g_file_create (log_file,
G_FILE_CREATE_PRIVATE,
cancellable,
error);
if (!log_stream)
goto out;
stream = G_OUTPUT_STREAM (log_stream);
}
app->log = stream;
}
#if SOUP_CHECK_VERSION(2, 48, 0)
server = soup_server_new (SOUP_SERVER_SERVER_HEADER, "ostree-httpd ", NULL);
if (!soup_server_listen_all (server, opt_port, 0, error))
@@ -459,13 +524,17 @@ ostree_builtin_trivial_httpd (int argc, char **argv, GCancellable *cancellable,
goto out;
g_signal_connect (dirmon, "changed", G_CALLBACK (on_dir_changed), app);
}
{
g_autofree gchar *path = g_file_get_path (app->root);
httpd_log (app, "serving at root %s\n", path);
}
while (app->running)
g_main_context_iteration (NULL, TRUE);
ret = TRUE;
out:
g_clear_object (&app->root);
g_clear_object (&app->log);
if (context)
g_option_context_free (context);
return ret;
+9 -2
View File
@@ -118,8 +118,15 @@ dump_commit (GVariant *variant,
g_print ("Version: %s\n", version);
}
g_print ("\n");
dump_indented_lines (subject);
if (subject[0])
{
g_print ("\n");
dump_indented_lines (subject);
}
else
{
g_print ("(no subject)\n");
}
if (body[0])
{
+3 -2
View File
@@ -22,9 +22,9 @@
#include "config.h"
#include "libglnx.h"
#include "ot-editor.h"
#include "libgsystem.h"
#include "libglnx.h"
#include <sys/wait.h>
#include <string.h>
@@ -101,7 +101,8 @@ ot_editor_prompt (OstreeRepo *repo,
goto out;
}
ret = gs_file_load_contents_utf8 (file, cancellable, error);
ret = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (file), NULL,
cancellable, error);
out:
if (file)
+1 -1
View File
@@ -27,9 +27,9 @@
#include <stdlib.h>
#include <string.h>
#include "ot-main.h"
#include "ostree.h"
#include "ot-admin-functions.h"
#include "ot-main.h"
#include "otutil.h"
static char *opt_repo;
+1 -1
View File
@@ -22,8 +22,8 @@
#pragma once
#include "ostree.h"
#include "libglnx.h"
#include "ostree.h"
typedef enum {
OSTREE_BUILTIN_FLAG_NONE = 0,