Imported Upstream version 2016.7

This commit is contained in:
Simon McVittie 2016-07-16 21:06:34 +01:00
commit 8d0c193392
58 changed files with 909 additions and 258 deletions

View File

@ -38,6 +38,9 @@ endif
if BUILDOPT_SYSTEMD
systemdsystemunit_DATA = src/boot/ostree-prepare-root.service \
src/boot/ostree-remount.service
# Allow the distcheck install under $prefix test to pass
AM_DISTCHECK_CONFIGURE_FLAGS += --with-systemdsystemunitdir='$${libdir}/systemd/system'
endif
if !BUILDOPT_BUILTIN_GRUB2_MKCONFIG

View File

@ -148,6 +148,7 @@ libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(
-fvisibility=hidden '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) extern'
libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions -Wl,--version-script=$(top_srcdir)/src/libostree/libostree.sym
libostree_1_la_LIBADD = libotutil.la libbupsplit.la libglnx.la libbsdiff.la libostree-kernel-args.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS)
EXTRA_libostree_1_la_DEPENDENCIES = $(top_srcdir)/src/libostree/libostree.sym
EXTRA_DIST += src/libostree/libostree.sym
@ -156,6 +157,11 @@ libostree_1_la_CFLAGS += $(OT_DEP_LIBARCHIVE_CFLAGS)
libostree_1_la_LIBADD += $(OT_DEP_LIBARCHIVE_LIBS)
endif
if BUILDOPT_LIBSYSTEMD
libostree_1_la_CFLAGS += $(LIBSYSTEMD_CFLAGS)
libostree_1_la_LIBADD += $(LIBSYSTEMD_LIBS)
endif
if USE_LIBSOUP
libostree_1_la_SOURCES += \
src/libostree/ostree-fetcher.h \

View File

@ -99,7 +99,7 @@ ostree_bin_shared_cflags = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/sr
ostree_bin_shared_ldadd = libglnx.la libbsdiff.la libotutil.la libostree-kernel-args.la libostree-1.la
ostree_CFLAGS = $(ostree_bin_shared_cflags) $(OT_INTERNAL_GIO_UNIX_CFLAGS) -I$(srcdir)/libglnx
ostree_LDADD = $(ostree_bin_shared_ldadd) $(OT_INTERNAL_GIO_UNIX_LIBS)
ostree_LDADD = $(ostree_bin_shared_ldadd) $(OT_INTERNAL_GIO_UNIX_LIBS) $(LIBSYSTEMD_LIBS)
if USE_LIBSOUP
ostree_SOURCES += \

View File

@ -36,6 +36,8 @@ libotutil_la_SOURCES = \
src/libotutil/ot-variant-utils.h \
src/libotutil/ot-gio-utils.c \
src/libotutil/ot-gio-utils.h \
src/libotutil/ot-log-utils.c \
src/libotutil/ot-log-utils.h \
src/libotutil/ot-gpg-utils.c \
src/libotutil/ot-gpg-utils.h \
src/libotutil/otutil.c \
@ -43,5 +45,5 @@ libotutil_la_SOURCES = \
src/libotutil/ot-tool-util.c \
src/libotutil/ot-tool-util.h \
$(NULL)
libotutil_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil -DLOCALEDIR=\"$(datadir)/locale\" $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS)
libotutil_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS)
libotutil_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil -DLOCALEDIR=\"$(datadir)/locale\" $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(LIBSYSTEMD_CFLAGS)
libotutil_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) $(LIBSYSTEMD_LIBS)

View File

@ -57,6 +57,7 @@ dist_test_scripts = \
tests/test-pull-metalink.sh \
tests/test-pull-summary-sigs.sh \
tests/test-pull-resume.sh \
tests/test-pull-repeated.sh \
tests/test-pull-untrusted.sh \
tests/test-pull-override-url.sh \
tests/test-local-pull.sh \
@ -232,12 +233,7 @@ EXTRA_DIST += \
tests/libostreetest.h \
tests/libtest.sh \
tests/gpg-verify-data/README.md \
tests/gpg-verify-data/lgpl2 \
tests/gpg-verify-data/lgpl2.sig \
tests/gpg-verify-data/pubring.gpg \
tests/gpg-verify-data/secring.gpg \
tests/gpg-verify-data/trustdb.gpg \
tests/gpg-verify-data/gpg.conf
$(NULL)
tests/libreaddir-rand.so: Makefile
$(AM_V_GEN) ln -fns ../.libs/libreaddir-rand.so tests
@ -245,7 +241,8 @@ ALL_LOCAL_RULES += tests/libreaddir-rand.so
CLEANFILES += tests/libreaddir-rand.so tests/ostree-symlink-stamp tests/ostree
tests/ostree-symlink-stamp: Makefile
@real_bin=`cd $(top_builddir) && libtool --mode=execute echo ostree`; \
@set -e; \
real_bin=`cd $(top_builddir) && ./libtool --mode=execute echo ostree`; \
ln -sf "$${real_bin}" tests/ostree; \
touch $@

View File

@ -60,12 +60,14 @@ libglnx_srcpath := $(srcdir)/libglnx
libglnx_cflags := $(OT_DEP_GIO_UNIX_CFLAGS) "-I$(libglnx_srcpath)"
libglnx_libs := $(OT_DEP_GIO_UNIX_LIBS)
include libglnx/Makefile-libglnx.am.inc
EXTRA_DIST += libglnx/Makefile-libglnx.am
noinst_LTLIBRARIES += libglnx.la
libbsdiff_srcpath := $(srcdir)/bsdiff
libbsdiff_cflags := $(OT_DEP_GIO_UNIX_CFLAGS) "-I$(bsdiff_srcpath)"
libbsdiff_libs := $(OT_DEP_GIO_UNIX_LIBS)
include bsdiff/Makefile-bsdiff.am.inc
EXTRA_DIST += bsdiff/Makefile-bsdiff.am
noinst_LTLIBRARIES += libbsdiff.la
include Makefile-otutil.am

View File

@ -300,6 +300,7 @@ ostree_repo_write_content_trusted
ostree_repo_write_content_async
ostree_repo_write_content_finish
ostree_repo_resolve_rev
ostree_repo_resolve_rev_ext
ostree_repo_list_refs
ostree_repo_list_refs_ext
ostree_repo_remote_list_refs

View File

@ -1,5 +1,5 @@
AC_PREREQ([2.63])
AC_INIT([ostree], [2016.6], [walters@verbum.org])
AC_INIT([ostree], [2016.7], [walters@verbum.org])
AC_CONFIG_HEADER([config.h])
AC_CONFIG_MACRO_DIR([buildutil])
AC_CONFIG_AUX_DIR([build-aux])
@ -17,7 +17,7 @@ AC_PROG_YACC
changequote(,)dnl
if test "x$GCC" = "xyes"; then
WARN_CFLAGS="-Wall -Wstrict-prototypes -Werror=missing-prototypes \
WARN_CFLAGS="-Wall -Wempty-body -Wstrict-prototypes -Werror=missing-prototypes \
-Werror=implicit-function-declaration \
-Werror=pointer-arith -Werror=init-self -Werror=format=2 \
-Werror=format-security \
@ -251,7 +251,13 @@ AC_ARG_WITH(mkinitcpio,
[with_mkinitcpio=no])
AM_CONDITIONAL(BUILDOPT_MKINITCPIO, test x$with_mkinitcpio = xyes)
AS_IF([test "x$with_dracut" = "xyes" || test "x$with_dracut" = "xyesbutnoconf" || test "x$with_mkinitcpio" = "xyes"], [
dnl We have separate checks for libsystemd and the unit dir for historical reasons
PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd], [have_libsystemd=yes], [have_libsystemd=no])
AM_CONDITIONAL(BUILDOPT_LIBSYSTEMD, test x$have_libsystemd = xyes)
AM_COND_IF(BUILDOPT_LIBSYSTEMD,
AC_DEFINE([HAVE_LIBSYSTEMD], 1, [Define if we have libsystemd]))
AS_IF([test "x$have_libsystemd" = "xyes"], [
with_systemd=yes
AC_ARG_WITH([systemdsystemunitdir],
AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
@ -309,6 +315,7 @@ echo "
libsoup (retrieve remote HTTP repositories): $with_soup
libsoup TLS client certs: $have_libsoup_client_certs
SELinux: $with_selinux
systemd: $have_libsystemd
libmount: $with_libmount
libarchive (parse tar files directly): $with_libarchive
static deltas: yes (always enabled now)
@ -322,7 +329,4 @@ AS_IF([test x$with_builtin_grub2_mkconfig = xyes], [
], [
echo " grub2-mkconfig path: $GRUB2_MKCONFIG"
])
AS_IF([test "x$with_systemd" = "xyes"], [
echo " systemd unit dir: $with_systemdsystemunitdir"
])
echo ""

View File

@ -268,3 +268,48 @@ developed by Fedora, Red Hat, and CentOS as part of Project Atomic.
This is a service that incrementally rebuilds and tests GNOME on every commit.
The need to make and distribute snapshots for this system was the original
inspiration for ostree.
## Docker
It makes sense to compare OSTree and Docker as far as *wire formats*
go. OSTree is not itself a container tool, but can be used as a
transport/storage format for container tools.
Docker has (at the time of this writing) two format versions (v1 and
v2). v1 is deprecated, so we'll look at [format version 2](https://github.com/docker/docker/blob/master/image/spec/v1.1.md).
A Docker image is a series of layers, and a layer is essentially JSON
metadata plus a tarball. The tarballs capture changes between layers,
including handling deleting files in higher layers.
Because the payload format is just tar, Docker hence captures
(numeric) uid/gid and xattrs.
This "layering" model is an interesting and powerful part of Docker,
allowing different images to reference a shared base. OSTree doesn't
implement this natively, but it's not difficult to implement in higher
level tools. For example in
[flatpak](https://github.com/flatpak/flatpak), there's a concept of a
SDK and runtime, and it would make a lot of sense for the SDK to
depend on the runtime, to avoid clients downloading data twice (even
if it's deduplicated on disk).
That gets to an advantage of OSTree over Docker; OSTree checksums
individual files (not tarballs), and uses this for deduplication.
Docker (natively) only shares storage via layering.
The biggest feature OSTree has over Docker though is support for
(static) deltas, and even without pre-configured static deltas, the
archive-z2 format has "natural" deltas. Particularly for a "base
operating system", one really wants on-wire deltas. It'd likely be
possible to extend Docker with this concept.
A core challenge both share is around metadata (particularly signing)
and search/discovery (the ostree `summary` file doesn't scale very
well).
One major issue Docker has is that it [checksums compressed data](https://github.com/projectatomic/skopeo/issues/11),
and furthermore the tar format is flexible, with multiple ways to represent data,
making it hard to impossible to reassemble and verify from on-disk state.
The [tarsum](https://github.com/docker/docker/blob/master/pkg/tarsum/tarsum_spec.md) effort
was intended to address this, but it was not adopted in the end for v2.

View File

@ -341,15 +341,19 @@ global:
ostree_repo_remote_fetch_summary_with_options;
} LIBOSTREE_2016.5;
LIBOSTREE_2016.7 {
global:
ostree_repo_resolve_rev_ext;
} LIBOSTREE_2016.6;
/* NOTE NOTE NOTE
* Versions above here are released. Only add symbols below this line.
* NOTE NOTE NOTE
*/
/* Uncomment this when adding a new symbol */
/*
/* UNCOMMENT WHEN ADDING THE FIRST NEW SYMBOL FOR 2016.8
LIBOSTREE_2016.7 {
global:
ostree_some_new_symbol;
} LIBOSTREE_2016.6;
*/
insert_symbol_here;
} LIBOSTREE_2016.8;
*/

View File

@ -83,8 +83,8 @@ _ostree_bootloader_grub2_query (OstreeBootloader *bootloader,
const char *fname;
g_autofree char *subdir_grub_cfg = NULL;
if (!gs_file_enumerator_iterate (direnum, &file_info, NULL,
cancellable, error))
if (!g_file_enumerator_iterate (direnum, &file_info, NULL,
cancellable, error))
goto out;
if (file_info == NULL)
break;

View File

@ -47,6 +47,7 @@ ostree_cmd__private__ (void)
static OstreeCmdPrivateVTable table = {
impl_ostree_generate_grub2_config,
_ostree_repo_static_delta_dump,
_ostree_repo_static_delta_query_exists,
_ostree_repo_static_delta_delete
};

View File

@ -27,6 +27,7 @@ G_BEGIN_DECLS
typedef struct {
gboolean (* ostree_generate_grub2_config) (OstreeSysroot *sysroot, int bootversion, int target_fd, GCancellable *cancellable, GError **error);
gboolean (* ostree_static_delta_dump) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error);
gboolean (* ostree_static_delta_query_exists) (OstreeRepo *repo, const char *delta_id, gboolean *out_exists, GCancellable *cancellable, GError **error);
gboolean (* ostree_static_delta_delete) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error);
} OstreeCmdPrivateVTable;

View File

@ -128,13 +128,6 @@ _ostree_loose_path (char *buf,
OstreeObjectType objtype,
OstreeRepoMode repo_mode);
void
_ostree_loose_path_with_suffix (char *buf,
const char *checksum,
OstreeObjectType objtype,
OstreeRepoMode repo_mode,
const char *suffix);
#define _OSTREE_METADATA_GPGSIGS_NAME "ostree.gpgsigs"
#define _OSTREE_METADATA_GPGSIGS_TYPE G_VARIANT_TYPE ("aay")

View File

@ -1047,6 +1047,8 @@ ostree_object_type_to_string (OstreeObjectType objtype)
return "commit";
case OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT:
return "tombstone-commit";
case OSTREE_OBJECT_TYPE_COMMIT_META:
return "commitmeta";
default:
g_assert_not_reached ();
return NULL;
@ -1070,6 +1072,10 @@ ostree_object_type_from_string (const char *str)
return OSTREE_OBJECT_TYPE_DIR_META;
else if (!strcmp (str, "commit"))
return OSTREE_OBJECT_TYPE_COMMIT;
else if (!strcmp (str, "tombstone-commit"))
return OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT;
else if (!strcmp (str, "commitmeta"))
return OSTREE_OBJECT_TYPE_COMMIT_META;
g_assert_not_reached ();
return 0;
}
@ -1269,7 +1275,7 @@ ostree_checksum_to_bytes_v (const char *checksum)
/**
* ostree_checksum_inplace_from_bytes: (skip)
* @csum: (array fixed-size=32): An binary checksum of length 32
* @buf: Output location, must be at least 65 bytes in length
* @buf: Output location, must be at least OSTREE_SHA256_STRING_LEN+1 bytes in length
*
* Overwrite the contents of @buf with stringified version of @csum.
*/
@ -1340,7 +1346,7 @@ ostree_checksum_b64_inplace_from_bytes (const guchar *csum,
char *
ostree_checksum_from_bytes (const guchar *csum)
{
char *ret = g_malloc (65);
char *ret = g_malloc (OSTREE_SHA256_STRING_LEN+1);
ostree_checksum_inplace_from_bytes (csum, ret);
return ret;
}
@ -1414,7 +1420,13 @@ _ostree_loose_path (char *buf,
OstreeObjectType objtype,
OstreeRepoMode mode)
{
_ostree_loose_path_with_suffix (buf, checksum, objtype, mode, "");
*buf = checksum[0];
buf++;
*buf = checksum[1];
buf++;
snprintf (buf, _OSTREE_LOOSE_PATH_MAX - 2, "/%s.%s%s",
checksum + 2, ostree_object_type_to_string (objtype),
(!OSTREE_OBJECT_TYPE_IS_META (objtype) && mode == OSTREE_REPO_MODE_ARCHIVE_Z2) ? "z" : "");
}
/**
@ -1442,33 +1454,6 @@ _ostree_header_gfile_info_new (mode_t mode, uid_t uid, gid_t gid)
return ret;
}
/*
* _ostree_loose_path_with_suffix:
* @buf: Output buffer, must be _OSTREE_LOOSE_PATH_MAX in size
* @checksum: ASCII checksum
* @objtype: Object type
* @mode: Repository mode
*
* Like _ostree_loose_path, but also append a further arbitrary
* suffix; useful for finding non-core objects.
*/
void
_ostree_loose_path_with_suffix (char *buf,
const char *checksum,
OstreeObjectType objtype,
OstreeRepoMode mode,
const char *suffix)
{
*buf = checksum[0];
buf++;
*buf = checksum[1];
buf++;
snprintf (buf, _OSTREE_LOOSE_PATH_MAX - 2, "/%s.%s%s%s",
checksum + 2, ostree_object_type_to_string (objtype),
(!OSTREE_OBJECT_TYPE_IS_META (objtype) && mode == OSTREE_REPO_MODE_ARCHIVE_Z2) ? "z" : "",
suffix);
}
/*
* _ostree_get_relative_object_path:
* @checksum: ASCII checksum string
@ -1484,7 +1469,7 @@ _ostree_get_relative_object_path (const char *checksum,
{
GString *path;
g_assert (strlen (checksum) == 64);
g_assert (strlen (checksum) == OSTREE_SHA256_STRING_LEN);
path = g_string_new ("objects/");
@ -1759,7 +1744,7 @@ ostree_validate_structureof_checksum_string (const char *checksum,
int i = 0;
size_t len = strlen (checksum);
if (len != 64)
if (len != OSTREE_SHA256_STRING_LEN)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid rev '%s'", checksum);
@ -1993,8 +1978,9 @@ ostree_validate_structureof_dirmeta (GVariant *dirmeta,
/**
* ostree_commit_get_parent:
* @commit_variant: Variant of type %OSTREE_OBJECT_TYPE_COMMIT
*
* Returns: Binary checksum with parent of @commit_variant, or %NULL if none
*
* Returns: Checksum of the parent commit of @commit_variant, or %NULL
* if none
*/
gchar *
ostree_commit_get_parent (GVariant *commit_variant)

View File

@ -51,8 +51,20 @@ G_BEGIN_DECLS
*/
#define OSTREE_MAX_RECURSION (256)
/**
* OSTREE_SHA256_DIGEST_LEN:
*
* Length of a sha256 digest when expressed as raw bytes
*/
#define OSTREE_SHA256_DIGEST_LEN (32)
/**
* OSTREE_SHA256_STRING_LEN:
*
* Length of a sha256 digest when expressed as a hexadecimal string
*/
#define OSTREE_SHA256_STRING_LEN (64)
/**
* OstreeObjectType:
* @OSTREE_OBJECT_TYPE_FILE: Content; regular file, symbolic link
@ -60,6 +72,7 @@ G_BEGIN_DECLS
* @OSTREE_OBJECT_TYPE_DIR_META: Directory metadata
* @OSTREE_OBJECT_TYPE_COMMIT: Toplevel object, refers to tree and dirmeta for root
* @OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT: Toplevel object, refers to a deleted commit
* @OSTREE_OBJECT_TYPE_COMMIT_META: Detached metadata for a commit
*
* Enumeration for core object types; %OSTREE_OBJECT_TYPE_FILE is for
* content, the other types are metadata.
@ -70,6 +83,7 @@ typedef enum {
OSTREE_OBJECT_TYPE_DIR_META = 3, /* .dirmeta */
OSTREE_OBJECT_TYPE_COMMIT = 4, /* .commit */
OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT = 5, /* .commit-tombstone */
OSTREE_OBJECT_TYPE_COMMIT_META = 6, /* .commitmeta */
} OstreeObjectType;
/**
@ -78,14 +92,14 @@ typedef enum {
*
* Returns: %TRUE if object type is metadata
*/
#define OSTREE_OBJECT_TYPE_IS_META(t) (t >= 2 && t <= 5)
#define OSTREE_OBJECT_TYPE_IS_META(t) (t >= 2 && t <= 6)
/**
* OSTREE_OBJECT_TYPE_LAST:
*
* Last valid object type; use this to validate ranges.
*/
#define OSTREE_OBJECT_TYPE_LAST OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT
#define OSTREE_OBJECT_TYPE_LAST OSTREE_OBJECT_TYPE_COMMIT_META
/**
* OSTREE_DIRMETA_GVARIANT_FORMAT:

View File

@ -44,7 +44,7 @@ typedef enum {
typedef struct {
volatile int ref_count;
SoupSession *session;
SoupSession *session; /* not referenced */
GMainContext *main_context;
GMainLoop *main_loop;
@ -88,8 +88,6 @@ typedef struct {
guint64 max_size;
guint64 current_size;
guint64 content_length;
GTask *task;
} OstreeFetcherPendingURI;
/* Used by session_thread_idle_add() */
@ -140,7 +138,8 @@ thread_closure_unref (ThreadClosure *thread_closure)
if (g_atomic_int_dec_and_test (&thread_closure->ref_count))
{
g_clear_object (&thread_closure->session);
/* The session thread should have cleared this by now. */
g_assert (thread_closure->session == NULL);
g_clear_pointer (&thread_closure->main_context, g_main_context_unref);
g_clear_pointer (&thread_closure->main_loop, g_main_loop_unref);
@ -156,11 +155,6 @@ thread_closure_unref (ThreadClosure *thread_closure)
g_free (thread_closure->tmpdir_name);
glnx_release_lock_file (&thread_closure->tmpdir_lock);
while (!g_queue_is_empty (&thread_closure->pending_queue))
g_object_unref (g_queue_pop_head (&thread_closure->pending_queue));
g_clear_pointer (&thread_closure->outstanding, g_hash_table_unref);
g_clear_pointer (&thread_closure->output_stream_set, g_hash_table_unref);
g_mutex_clear (&thread_closure->output_stream_set_lock);
@ -452,13 +446,15 @@ static gpointer
ostree_fetcher_session_thread (gpointer data)
{
ThreadClosure *closure = data;
g_autoptr(GMainContext) mainctx = g_main_context_ref (closure->main_context);
gint max_conns;
/* This becomes the GMainContext that SoupSession schedules async
* callbacks and emits signals from. Make it the thread-default
* context for this thread before creating the session. */
g_main_context_push_thread_default (closure->main_context);
g_main_context_push_thread_default (mainctx);
/* We retain ownership of the SoupSession reference. */
closure->session = soup_session_async_new_with_options (SOUP_SESSION_USER_AGENT, "ostree ",
SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
@ -481,10 +477,21 @@ ostree_fetcher_session_thread (gpointer data)
g_main_loop_run (closure->main_loop);
g_main_context_pop_thread_default (closure->main_context);
/* Since the ThreadClosure may be finalized from any thread we
* unreference all data related to the SoupSession ourself to ensure
* it's freed in the same thread where it was created. */
g_clear_pointer (&closure->outstanding, g_hash_table_unref);
while (!g_queue_is_empty (&closure->pending_queue))
g_object_unref (g_queue_pop_head (&closure->pending_queue));
g_clear_pointer (&closure->session, g_object_unref);
thread_closure_unref (closure);
/* Do this last, since libsoup uses g_main_current_source() which
* relies on it.
*/
g_main_context_pop_thread_default (mainctx);
return NULL;
}

View File

@ -23,6 +23,7 @@
#include "config.h"
#include "libglnx.h"
#include "ostree-gpg-verifier.h"
#include "ostree-gpg-verify-result-private.h"
#include "otutil.h"
@ -253,8 +254,8 @@ _ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier *self,
GFile *path;
const char *name;
if (!gs_file_enumerator_iterate (enumerator, &file_info, &path,
cancellable, error))
if (!g_file_enumerator_iterate (enumerator, &file_info, &path,
cancellable, error))
goto out;
if (file_info == NULL)
break;

View File

@ -346,7 +346,7 @@ checkout_file_hardlink (OstreeRepo *self,
again:
if (linkat (srcfd, loose_path, destination_dfd, destination_name, 0) != -1)
ret_was_supported = TRUE;
else if (errno == EMLINK || errno == EXDEV || errno == EPERM)
else if (!options->no_copy_fallback && (errno == EMLINK || errno == EXDEV || errno == EPERM))
{
/* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the
* optimization of hardlinking instead of copying.
@ -480,7 +480,7 @@ checkout_one_file_at (OstreeRepo *repo,
key = g_new (OstreeDevIno, 1);
key->dev = stbuf.st_dev;
key->ino = stbuf.st_ino;
memcpy (key->checksum, checksum, 65);
memcpy (key->checksum, checksum, OSTREE_SHA256_STRING_LEN+1);
g_hash_table_add ((GHashTable*)options->devino_to_csum_cache, key);
}
@ -696,8 +696,8 @@ checkout_tree_at (OstreeRepo *self,
GFile *src_child;
const char *name;
if (!gs_file_enumerator_iterate (dir_enum, &file_info, &src_child,
cancellable, error))
if (!g_file_enumerator_iterate (dir_enum, &file_info, &src_child,
cancellable, error))
goto out;
if (file_info == NULL)
break;

View File

@ -1173,43 +1173,31 @@ rename_pending_loose_objects (OstreeRepo *self,
GError **error)
{
gboolean ret = FALSE;
gs_dirfd_iterator_cleanup GSDirFdIterator dfd_iter = { 0, };
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
if (!gs_dirfd_iterator_init_at (self->commit_stagedir_fd, ".", FALSE, &dfd_iter, error))
if (!glnx_dirfd_iterator_init_at (self->commit_stagedir_fd, ".", FALSE, &dfd_iter, error))
goto out;
/* Iterate over the outer checksum dir */
while (TRUE)
{
struct dirent *dent;
gs_dirfd_iterator_cleanup GSDirFdIterator child_dfd_iter = { 0, };
struct stat stbuf;
int res;
g_auto(GLnxDirFdIterator) child_dfd_iter = { 0, };
if (!gs_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
goto out;
if (dent == NULL)
break;
do
res = fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW);
while (G_UNLIKELY (res == -1 && errno == EINTR));
if (res == -1)
{
glnx_set_error_from_errno (error);
goto out;
}
if (!S_ISDIR (stbuf.st_mode))
if (dent->d_type != DT_DIR)
continue;
/* All object directories only have two character entries */
if (strlen (dent->d_name) != 2)
continue;
if (!gs_dirfd_iterator_init_at (dfd_iter.fd, dent->d_name, FALSE,
&child_dfd_iter, error))
if (!glnx_dirfd_iterator_init_at (dfd_iter.fd, dent->d_name, FALSE,
&child_dfd_iter, error))
goto out;
/* Iterate over inner checksum dir */
@ -1218,9 +1206,8 @@ rename_pending_loose_objects (OstreeRepo *self,
struct dirent *child_dent;
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
if (!gs_dirfd_iterator_next_dent (&child_dfd_iter, &child_dent, cancellable, error))
if (!glnx_dirfd_iterator_next_dent (&child_dfd_iter, &child_dent, cancellable, error))
goto out;
if (child_dent == NULL)
break;
@ -2071,8 +2058,7 @@ _ostree_repo_get_commit_metadata_loose_path (OstreeRepo *self,
const char *checksum)
{
char buf[_OSTREE_LOOSE_PATH_MAX];
_ostree_loose_path_with_suffix (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT, self->mode,
"meta");
_ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode);
return g_file_resolve_relative_path (self->objects_dir, buf);
}
@ -2412,7 +2398,7 @@ write_directory_to_mtree_internal (OstreeRepo *self,
GError **error);
static gboolean
write_dfd_iter_to_mtree_internal (OstreeRepo *self,
GSDirFdIterator *src_dfd_iter,
GLnxDirFdIterator *src_dfd_iter,
OstreeMutableTree *mtree,
OstreeRepoCommitModifier *modifier,
GPtrArray *path,
@ -2423,7 +2409,7 @@ static gboolean
write_directory_content_to_mtree_internal (OstreeRepo *self,
OstreeRepoFile *repo_dir,
GFileEnumerator *dir_enum,
GSDirFdIterator *dfd_iter,
GLnxDirFdIterator *dfd_iter,
GFileInfo *child_info,
OstreeMutableTree *mtree,
OstreeRepoCommitModifier *modifier,
@ -2488,9 +2474,9 @@ write_directory_content_to_mtree_internal (OstreeRepo *self,
}
else
{
gs_dirfd_iterator_cleanup GSDirFdIterator child_dfd_iter = { 0, };
g_auto(GLnxDirFdIterator) child_dfd_iter = { 0, };
if (!gs_dirfd_iterator_init_at (dfd_iter->fd, name, FALSE, &child_dfd_iter, error))
if (!glnx_dirfd_iterator_init_at (dfd_iter->fd, name, FALSE, &child_dfd_iter, error))
goto out;
if (!write_dfd_iter_to_mtree_internal (self, &child_dfd_iter, child_mtree,
@ -2672,8 +2658,8 @@ write_directory_to_mtree_internal (OstreeRepo *self,
{
GFileInfo *child_info;
if (!gs_file_enumerator_iterate (dir_enum, &child_info, NULL,
cancellable, error))
if (!g_file_enumerator_iterate (dir_enum, &child_info, NULL,
cancellable, error))
goto out;
if (child_info == NULL)
break;
@ -2693,7 +2679,7 @@ write_directory_to_mtree_internal (OstreeRepo *self,
static gboolean
write_dfd_iter_to_mtree_internal (OstreeRepo *self,
GSDirFdIterator *src_dfd_iter,
GLnxDirFdIterator *src_dfd_iter,
OstreeMutableTree *mtree,
OstreeRepoCommitModifier *modifier,
GPtrArray *path,
@ -2760,9 +2746,8 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self,
g_autoptr(GFileInfo) child_info = NULL;
const char *loose_checksum;
if (!gs_dirfd_iterator_next_dent (src_dfd_iter, &dent, cancellable, error))
if (!glnx_dirfd_iterator_next_dent (src_dfd_iter, &dent, cancellable, error))
goto out;
if (dent == NULL)
break;
@ -2888,15 +2873,14 @@ ostree_repo_write_dfd_to_mtree (OstreeRepo *self,
{
gboolean ret = FALSE;
g_autoptr(GPtrArray) pathbuilder = NULL;
gs_dirfd_iterator_cleanup GSDirFdIterator dfd_iter = { 0, };
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
if (modifier && modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES)
self->generate_sizes = TRUE;
pathbuilder = g_ptr_array_new ();
if (!gs_dirfd_iterator_init_at (dfd, path, FALSE,
&dfd_iter, error))
if (!glnx_dirfd_iterator_init_at (dfd, path, FALSE, &dfd_iter, error))
goto out;
if (!write_dfd_iter_to_mtree_internal (self, &dfd_iter, mtree, modifier, pathbuilder,
@ -2952,7 +2936,7 @@ ostree_repo_write_mtree (OstreeRepo *self,
g_autoptr(GHashTable) dir_contents_checksums = NULL;
g_autoptr(GVariant) serialized_tree = NULL;
g_autofree guchar *contents_csum = NULL;
char contents_checksum_buf[65];
char contents_checksum_buf[OSTREE_SHA256_STRING_LEN+1];
dir_contents_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, (GDestroyNotify)g_free);

View File

@ -113,9 +113,9 @@ _ostree_repo_file_new_root (OstreeRepo *repo,
g_return_val_if_fail (repo != NULL, NULL);
g_return_val_if_fail (contents_checksum != NULL, NULL);
g_return_val_if_fail (strlen (contents_checksum) == 64, NULL);
g_return_val_if_fail (strlen (contents_checksum) == OSTREE_SHA256_STRING_LEN, NULL);
g_return_val_if_fail (metadata_checksum != NULL, NULL);
g_return_val_if_fail (strlen (metadata_checksum) == 64, NULL);
g_return_val_if_fail (strlen (metadata_checksum) == OSTREE_SHA256_STRING_LEN, NULL);
self = g_object_new (OSTREE_TYPE_REPO_FILE, NULL);
self->repo = g_object_ref (repo);
@ -152,12 +152,12 @@ _ostree_repo_file_new_for_commit (OstreeRepo *repo,
g_autoptr(GVariant) commit_v = NULL;
g_autoptr(GVariant) tree_contents_csum_v = NULL;
g_autoptr(GVariant) tree_metadata_csum_v = NULL;
char tree_contents_csum[65];
char tree_metadata_csum[65];
char tree_contents_csum[OSTREE_SHA256_STRING_LEN + 1];
char tree_metadata_csum[OSTREE_SHA256_STRING_LEN + 1];
g_return_val_if_fail (repo != NULL, NULL);
g_return_val_if_fail (commit != NULL, NULL);
g_return_val_if_fail (strlen (commit) == 64, NULL);
g_return_val_if_fail (strlen (commit) == OSTREE_SHA256_STRING_LEN, NULL);
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
commit, &commit_v, error))
@ -807,7 +807,7 @@ ostree_repo_file_tree_query_child (OstreeRepoFile *self,
g_autoptr(GVariant) dirs_variant = NULL;
g_autoptr(GVariant) content_csum_v = NULL;
g_autoptr(GVariant) meta_csum_v = NULL;
char tmp_checksum[65];
char tmp_checksum[OSTREE_SHA256_STRING_LEN+1];
GFileAttributeMatcher *matcher = NULL;
if (!ostree_repo_file_ensure_resolved (self, error))

View File

@ -1075,8 +1075,8 @@ write_directory_to_libarchive_recurse (OstreeRepo *self,
GFileInfo *file_info;
GFile *path;
if (!gs_file_enumerator_iterate (dir_enum, &file_info, &path,
cancellable, error))
if (!g_file_enumerator_iterate (dir_enum, &file_info, &path,
cancellable, error))
goto out;
if (file_info == NULL)
break;

View File

@ -120,7 +120,7 @@ struct OstreeRepo {
typedef struct {
dev_t dev;
ino_t ino;
char checksum[65];
char checksum[OSTREE_SHA256_STRING_LEN+1];
} OstreeDevIno;
#define OSTREE_REPO_TMPDIR_STAGING "staging-"

View File

@ -22,12 +22,12 @@
#include "config.h"
#include "libglnx.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"
@ -415,6 +415,26 @@ fetch_uri_contents_utf8_sync (OtPullData *pull_data,
return ret;
}
static gboolean
write_commitpartial_for (OtPullData *pull_data,
const char *checksum,
GError **error)
{
g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (checksum);
glnx_fd_close int fd = -1;
fd = openat (pull_data->repo->repo_dir_fd, commitpartial_path, O_EXCL | O_CREAT | O_WRONLY | O_CLOEXEC | O_NOCTTY, 0600);
if (fd == -1)
{
if (errno != EEXIST)
{
glnx_set_error_from_errno (error);
return FALSE;
}
}
return TRUE;
}
static void
enqueue_one_object_request (OtPullData *pull_data,
const char *checksum,
@ -683,6 +703,7 @@ content_fetch_on_complete (GObject *object,
const char *checksum;
g_autofree char *checksum_obj = NULL;
OstreeObjectType objtype;
gboolean free_fetch_data = TRUE;
temp_path = _ostree_fetcher_request_uri_with_partial_finish (fetcher, result, error);
if (!temp_path)
@ -741,11 +762,17 @@ content_fetch_on_complete (GObject *object,
object_input, length,
cancellable,
content_fetch_on_write_complete, fetch_data);
free_fetch_data = FALSE;
}
out:
pull_data->n_outstanding_content_fetches--;
check_outstanding_requests_handle_error (pull_data, local_error);
if (free_fetch_data)
{
g_variant_unref (fetch_data->object);
g_free (fetch_data);
}
}
static void
@ -809,7 +836,7 @@ meta_fetch_on_complete (GObject *object,
GError *local_error = NULL;
GError **error = &local_error;
glnx_fd_close int fd = -1;
gboolean free_fetch_data = FALSE;
gboolean free_fetch_data = TRUE;
ostree_object_name_deserialize (fetch_data->object, &checksum, &objtype);
checksum_obj = ostree_object_to_string (checksum, objtype);
@ -875,8 +902,6 @@ 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
{
@ -889,24 +914,15 @@ meta_fetch_on_complete (GObject *object,
/* Write the commitpartial file now while we're still fetching data */
if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
{
g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (checksum);
glnx_fd_close int fd = -1;
fd = openat (pull_data->repo->repo_dir_fd, commitpartial_path, O_EXCL | O_CREAT | O_WRONLY | O_CLOEXEC | O_NOCTTY, 0600);
if (fd == -1)
{
if (errno != EEXIST)
{
glnx_set_error_from_errno (error);
goto out;
}
}
if (!write_commitpartial_for (pull_data, checksum, error))
goto out;
}
ostree_repo_write_metadata_async (pull_data->repo, objtype, checksum, metadata,
pull_data->cancellable,
on_metadata_written, fetch_data);
pull_data->n_outstanding_metadata_write_requests++;
free_fetch_data = FALSE;
}
out:
@ -914,7 +930,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 || free_fetch_data)
if (free_fetch_data)
{
g_variant_unref (fetch_data->object);
g_free (fetch_data);
@ -968,6 +984,7 @@ static_deltapart_fetch_on_complete (GObject *object,
GError *local_error = NULL;
GError **error = &local_error;
glnx_fd_close int fd = -1;
gboolean free_fetch_data = TRUE;
g_debug ("fetch static delta part %s complete", fetch_data->expected_checksum);
@ -1005,13 +1022,14 @@ static_deltapart_fetch_on_complete (GObject *object,
on_static_delta_written,
fetch_data);
pull_data->n_outstanding_deltapart_write_requests++;
free_fetch_data = FALSE;
out:
g_assert (pull_data->n_outstanding_deltapart_fetches > 0);
pull_data->n_outstanding_deltapart_fetches--;
pull_data->n_fetched_deltaparts++;
check_outstanding_requests_handle_error (pull_data, local_error);
if (local_error)
if (free_fetch_data)
fetch_static_delta_data_free (fetch_data);
}
@ -1096,7 +1114,7 @@ scan_commit_object (OtPullData *pull_data,
}
else if (parent_csum_bytes != NULL && depth > 0)
{
char parent_checksum[65];
char parent_checksum[OSTREE_SHA256_STRING_LEN+1];
gpointer parent_depthp;
int parent_depth;
@ -1205,11 +1223,18 @@ scan_one_metadata_object_c (OtPullData *pull_data,
if (pull_data->remote_repo_local)
{
if (!is_stored &&
!ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local,
objtype, tmp_checksum, !pull_data->is_untrusted,
cancellable, error))
goto out;
if (!is_stored)
{
if (!ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local,
objtype, tmp_checksum, !pull_data->is_untrusted,
cancellable, error))
goto out;
if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
{
if (!write_commitpartial_for (pull_data, tmp_checksum, error))
goto out;
}
}
is_stored = TRUE;
is_requested = TRUE;
}
@ -1316,8 +1341,7 @@ enqueue_one_object_request (OtPullData *pull_data,
if (is_detached_meta)
{
char buf[_OSTREE_LOOSE_PATH_MAX];
_ostree_loose_path_with_suffix (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT,
pull_data->remote_mode, "meta");
_ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, pull_data->remote_mode);
obj_uri = suburi_new (pull_data->base_uri, "objects", buf, NULL);
}
else

View File

@ -100,14 +100,51 @@ write_checksum_file_at (OstreeRepo *self,
{
size_t l = strlen (sha256);
char *bufnl = alloca (l + 2);
g_autoptr(GError) temp_error = NULL;
memcpy (bufnl, sha256, l);
bufnl[l] = '\n';
bufnl[l+1] = '\0';
if (!_ostree_repo_file_replace_contents (self, dfd, name, (guint8*)bufnl, l + 1,
cancellable, error))
goto out;
cancellable, &temp_error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY))
{
g_autoptr(GHashTable) refs = NULL;
GHashTableIter hashiter;
gpointer hashkey, hashvalue;
g_clear_error (&temp_error);
if (!ostree_repo_list_refs (self, name, &refs, cancellable, error))
goto out;
g_hash_table_iter_init (&hashiter, refs);
while ((g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue)))
{
if (strcmp (name, (char *)hashkey) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Conflict: %s exists under %s when attempting write", (char*)hashkey, name);
goto out;
}
}
if (!glnx_shutil_rm_rf_at (dfd, name, cancellable, error))
goto out;
if (!_ostree_repo_file_replace_contents (self, dfd, name, (guint8*)bufnl, l + 1,
cancellable, error))
goto out;
}
else
{
g_propagate_error (error, g_steal_pointer (&temp_error));
goto out;
}
}
}
ret = TRUE;
@ -162,6 +199,7 @@ resolve_refspec (OstreeRepo *self,
const char *remote,
const char *ref,
gboolean allow_noent,
gboolean fallback_remote,
char **out_rev,
GError **error);
@ -170,6 +208,7 @@ resolve_refspec_fallback (OstreeRepo *self,
const char *remote,
const char *ref,
gboolean allow_noent,
gboolean fallback_remote,
char **out_rev,
GCancellable *cancellable,
GError **error)
@ -179,8 +218,8 @@ resolve_refspec_fallback (OstreeRepo *self,
if (self->parent_repo)
{
if (!resolve_refspec (self->parent_repo, remote, ref,
allow_noent, &ret_rev, error))
if (!resolve_refspec (self->parent_repo, remote, ref, allow_noent,
fallback_remote, &ret_rev, error))
goto out;
}
else if (!allow_noent)
@ -204,6 +243,7 @@ resolve_refspec (OstreeRepo *self,
const char *remote,
const char *ref,
gboolean allow_noent,
gboolean fallback_remote,
char **out_rev,
GError **error)
{
@ -233,7 +273,7 @@ resolve_refspec (OstreeRepo *self,
if (!ot_openat_ignore_enoent (self->repo_dir_fd, local_ref, &target_fd, error))
goto out;
if (target_fd == -1)
if (target_fd == -1 && fallback_remote)
{
local_ref = glnx_strjoina ("refs/remotes/", ref);
@ -263,7 +303,7 @@ resolve_refspec (OstreeRepo *self,
}
else
{
if (!resolve_refspec_fallback (self, remote, ref, allow_noent,
if (!resolve_refspec_fallback (self, remote, ref, allow_noent, fallback_remote,
&ret_rev, cancellable, error))
goto out;
}
@ -304,10 +344,10 @@ ostree_repo_resolve_partial_checksum (OstreeRepo *self,
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* If the input is longer than 64 chars or contains non-hex chars,
/* If the input is longer than OSTREE_SHA256_STRING_LEN chars or contains non-hex chars,
don't bother looking for it as an object */
off = strspn (refspec, hexchars);
if (off > 64 || refspec[off] != '\0')
if (off > OSTREE_SHA256_STRING_LEN || refspec[off] != '\0')
return TRUE;
/* this looks through all objects and adds them to the ref_list if:
@ -351,23 +391,13 @@ ostree_repo_resolve_partial_checksum (OstreeRepo *self,
return ret;
}
/**
* ostree_repo_resolve_rev:
* @self: Repo
* @refspec: A refspec
* @allow_noent: Do not throw an error if refspec does not exist
* @out_rev: (out) (transfer full): A checksum,or %NULL if @allow_noent is true and it does not exist
* @error: Error
*
* Look up the given refspec, returning the checksum it references in
* the parameter @out_rev.
*/
gboolean
ostree_repo_resolve_rev (OstreeRepo *self,
const char *refspec,
gboolean allow_noent,
char **out_rev,
GError **error)
static gboolean
_ostree_repo_resolve_rev_internal (OstreeRepo *self,
const char *refspec,
gboolean allow_noent,
gboolean fallback_remote,
char **out_rev,
GError **error)
{
gboolean ret = FALSE;
g_autofree char *ret_rev = NULL;
@ -419,7 +449,7 @@ ostree_repo_resolve_rev (OstreeRepo *self,
goto out;
if (!resolve_refspec (self, remote, ref, allow_noent,
&ret_rev, error))
fallback_remote, &ret_rev, error))
goto out;
}
}
@ -430,6 +460,53 @@ ostree_repo_resolve_rev (OstreeRepo *self,
return ret;
}
/**
* ostree_repo_resolve_rev:
* @self: Repo
* @refspec: A refspec
* @allow_noent: Do not throw an error if refspec does not exist
* @out_rev: (out) (transfer full): A checksum,or %NULL if @allow_noent is true and it does not exist
* @error: Error
*
* Look up the given refspec, returning the checksum it references in
* the parameter @out_rev. Will fall back on remote directory if cannot
* find the given refspec in local.
*/
gboolean
ostree_repo_resolve_rev (OstreeRepo *self,
const char *refspec,
gboolean allow_noent,
char **out_rev,
GError **error)
{
return _ostree_repo_resolve_rev_internal (self, refspec, allow_noent, TRUE, out_rev, error);
}
/**
* ostree_repo_resolve_rev_ext:
* @self: Repo
* @refspec: A refspec
* @allow_noent: Do not throw an error if refspec does not exist
* @flags: Options controlling behavior
* @out_rev: (out) (transfer full): A checksum,or %NULL if @allow_noent is true and it does not exist
* @error: Error
*
* Look up the given refspec, returning the checksum it references in
* the parameter @out_rev. Differently from ostree_repo_resolve_rev(),
* this will not fall back to searching through remote repos if a
* local ref is specified but not found.
*/
gboolean
ostree_repo_resolve_rev_ext (OstreeRepo *self,
const char *refspec,
gboolean allow_noent,
OstreeRepoResolveRevExtFlags flags,
char **out_rev,
GError **error)
{
return _ostree_repo_resolve_rev_internal (self, refspec, allow_noent, FALSE, out_rev, error);
}
static gboolean
enumerate_refs_recurse (OstreeRepo *repo,
const char *remote,
@ -703,7 +780,7 @@ ostree_repo_remote_list_refs (OstreeRepo *self,
{
const char *ref_name = NULL;
g_autoptr(GVariant) csum_v = NULL;
char tmp_checksum[65];
char tmp_checksum[OSTREE_SHA256_STRING_LEN+1];
g_variant_get_child (child, 0, "&s", &ref_name);
@ -772,8 +849,10 @@ _ostree_repo_write_ref (OstreeRepo *self,
goto out;
}
if (!glnx_opendirat (refs_remotes_dfd, remote, TRUE, &dfd, error))
dfd = glnx_opendirat_with_errno (refs_remotes_dfd, remote, TRUE);
if (dfd < 0 && (errno != ENOENT || rev != NULL))
{
glnx_set_error_from_errno (error);
g_prefix_error (error, "Opening remotes/ dir %s: ", remote);
goto out;
}
@ -781,13 +860,16 @@ _ostree_repo_write_ref (OstreeRepo *self,
if (rev == NULL)
{
if (unlinkat (dfd, ref, 0) != 0)
if (dfd >= 0)
{
if (errno != ENOENT)
{
glnx_set_error_from_errno (error);
goto out;
}
if (unlinkat (dfd, ref, 0) != 0)
{
if (errno != ENOENT)
{
glnx_set_error_from_errno (error);
goto out;
}
}
}
}
else

View File

@ -94,8 +94,8 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
GFileInfo *file_info;
GFile *child;
if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
NULL, error))
if (!g_file_enumerator_iterate (dir_enum, &file_info, &child,
NULL, error))
goto out;
if (file_info == NULL)
break;
@ -117,8 +117,8 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
const char *name1;
const char *name2;
if (!gs_file_enumerator_iterate (dir_enum2, &file_info2, &child2,
NULL, error))
if (!g_file_enumerator_iterate (dir_enum2, &file_info2, &child2,
NULL, error))
goto out;
if (file_info2 == NULL)
break;
@ -136,7 +136,7 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
{
g_autofree char *buf = g_strconcat (name1, name2, NULL);
GString *out = g_string_new ("");
char checksum[65];
char checksum[OSTREE_SHA256_STRING_LEN+1];
guchar csum[OSTREE_SHA256_DIGEST_LEN];
const char *dash = strchr (buf, '-');
@ -187,7 +187,7 @@ _ostree_repo_static_delta_part_have_all_objects (OstreeRepo *repo,
{
guint8 objtype = *checksums_data;
const guint8 *csum = checksums_data + 1;
char tmp_checksum[65];
char tmp_checksum[OSTREE_SHA256_STRING_LEN+1];
if (G_UNLIKELY(!ostree_validate_structureof_objtype (objtype, error)))
goto out;
@ -354,7 +354,7 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self,
guint64 size;
guint64 usize;
const guchar *csum;
char checksum[65];
char checksum[OSTREE_SHA256_STRING_LEN+1];
gboolean have_all;
g_autoptr(GInputStream) part_in = NULL;
g_autoptr(GBytes) delta_data = NULL;
@ -819,6 +819,38 @@ _ostree_repo_static_delta_delete (OstreeRepo *self,
return ret;
}
gboolean
_ostree_repo_static_delta_query_exists (OstreeRepo *self,
const char *delta_id,
gboolean *out_exists,
GCancellable *cancellable,
GError **error)
{
g_autofree char *from = NULL;
g_autofree char *to = NULL;
g_autofree char *superblock_path = NULL;
struct stat stbuf;
_ostree_parse_delta_name (delta_id, &from, &to);
superblock_path = _ostree_get_relative_static_delta_superblock_path (from, to);
if (fstatat (self->repo_dir_fd, superblock_path, &stbuf, 0) < 0)
{
if (errno == ENOENT)
{
*out_exists = FALSE;
return TRUE;
}
else
{
glnx_set_error_from_errno (error);
return FALSE;
}
}
*out_exists = TRUE;
return TRUE;
}
gboolean
_ostree_repo_static_delta_dump (OstreeRepo *self,
const char *delta_id,

View File

@ -190,6 +190,13 @@ _ostree_delta_compute_similar_objects (OstreeRepo *repo,
GCancellable *cancellable,
GError **error);
gboolean
_ostree_repo_static_delta_query_exists (OstreeRepo *repo,
const char *delta_id,
gboolean *out_exists,
GCancellable *cancellable,
GError **error);
gboolean
_ostree_repo_static_delta_dump (OstreeRepo *repo,
const char *delta_id,

View File

@ -60,7 +60,7 @@ typedef struct {
OstreeRepoContentBareCommit barecommitstate;
guint64 content_size;
GOutputStream *content_out;
char checksum[65];
char checksum[OSTREE_SHA256_STRING_LEN+1];
char *read_source_object;
int read_source_fd;
gboolean have_obj;
@ -78,7 +78,7 @@ typedef struct {
typedef struct {
StaticDeltaExecutionState *state;
char checksum[65];
char checksum[OSTREE_SHA256_STRING_LEN+1];
} StaticDeltaContentWrite;
typedef gboolean (*DispatchOpFunc) (OstreeRepo *repo,

View File

@ -34,8 +34,8 @@ struct _OstreeRepoRealCommitTraverseIter {
const char *name;
OstreeRepoCommitIterResult state;
guint idx;
char checksum_content[65];
char checksum_meta[65];
char checksum_content[OSTREE_SHA256_STRING_LEN+1];
char checksum_meta[OSTREE_SHA256_STRING_LEN+1];
};
/**

View File

@ -2070,8 +2070,8 @@ append_remotes_d (OstreeRepo *self,
const char *name;
guint32 type;
if (!gs_file_enumerator_iterate (direnum, &file_info, &path,
NULL, error))
if (!g_file_enumerator_iterate (direnum, &file_info, &path,
NULL, error))
goto out;
if (file_info == NULL)
break;
@ -2445,7 +2445,7 @@ list_loose_objects_at (OstreeRepo *self,
const char *name = dent->d_name;
const char *dot;
OstreeObjectType objtype;
char buf[65];
char buf[OSTREE_SHA256_STRING_LEN+1];
if (strcmp (name, ".") == 0 ||
strcmp (name, "..") == 0)
@ -2715,18 +2715,29 @@ _ostree_repo_read_bare_fd (OstreeRepo *self,
GError **error)
{
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
g_assert (self->mode == OSTREE_REPO_MODE_BARE ||
self->mode == OSTREE_REPO_MODE_BARE_USER);
_ostree_loose_path (loose_path_buf, checksum, OSTREE_OBJECT_TYPE_FILE, self->mode);
*out_fd = openat (self->objects_dir_fd, loose_path_buf, O_RDONLY | O_CLOEXEC);
if (*out_fd < 0)
if (!ot_openat_ignore_enoent (self->objects_dir_fd, loose_path_buf, out_fd, error))
return FALSE;
if (*out_fd == -1)
{
glnx_set_error_from_errno (error);
if (self->parent_repo)
return _ostree_repo_read_bare_fd (self->parent_repo,
checksum,
out_fd,
cancellable,
error);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"No such file object %s", checksum);
return FALSE;
}
return TRUE;
}
@ -2837,9 +2848,12 @@ ostree_repo_load_file (OstreeRepo *self,
*/
if (S_ISLNK (mode) || out_input)
{
if (!gs_file_openat_noatime (self->objects_dir_fd, loose_path_buf, &fd,
cancellable, error))
goto out;
fd = openat (self->objects_dir_fd, loose_path_buf, O_RDONLY | O_CLOEXEC);
if (fd < 0)
{
glnx_set_error_from_errno (error);
goto out;
}
}
if (S_ISREG (mode) && out_input)
@ -2876,9 +2890,12 @@ ostree_repo_load_file (OstreeRepo *self,
{
glnx_fd_close int fd = -1;
if (!gs_file_openat_noatime (self->objects_dir_fd, loose_path_buf, &fd,
cancellable, error))
goto out;
fd = openat (self->objects_dir_fd, loose_path_buf, O_RDONLY | O_CLOEXEC);
if (fd < 0)
{
glnx_set_error_from_errno (error);
goto out;
}
if (out_xattrs)
{
@ -3114,8 +3131,7 @@ ostree_repo_delete_object (OstreeRepo *self,
{
char meta_loose[_OSTREE_LOOSE_PATH_MAX];
_ostree_loose_path_with_suffix (meta_loose, sha256,
OSTREE_OBJECT_TYPE_COMMIT, self->mode, "meta");
_ostree_loose_path (meta_loose, sha256, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode);
do
res = unlinkat (self->objects_dir_fd, meta_loose, 0);
@ -4825,7 +4841,6 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd,
while (tmpdir_name == NULL)
{
gs_dirfd_iterator_cleanup GSDirFdIterator child_dfd_iter = { 0, };
struct dirent *dent;
glnx_fd_close int existing_tmpdir_fd = -1;
g_autoptr(GError) local_error = NULL;

View File

@ -382,6 +382,22 @@ gboolean ostree_repo_resolve_rev (OstreeRepo *self,
char **out_rev,
GError **error);
/**
* OstreeRepoResolveRevExtFlags:
* @OSTREE_REPO_RESOLVE_REV_EXT_NONE: No flags.
*/
typedef enum {
OSTREE_REPO_RESOLVE_REV_EXT_NONE = 0,
} OstreeRepoResolveRevExtFlags;
_OSTREE_PUBLIC
gboolean ostree_repo_resolve_rev_ext (OstreeRepo *self,
const char *refspec,
gboolean allow_noent,
OstreeRepoResolveRevExtFlags flags,
char **out_rev,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_repo_list_refs (OstreeRepo *self,
const char *refspec_prefix,
@ -734,7 +750,8 @@ typedef struct {
guint enable_uncompressed_cache : 1;
guint disable_fsync : 1;
guint process_whiteouts : 1;
guint reserved : 29;
guint no_copy_fallback : 1;
guint reserved : 28;
const char *subpath;
@ -866,7 +883,7 @@ gboolean ostree_repo_traverse_commit_union (OstreeRepo *repo,
struct _OstreeRepoCommitTraverseIter {
gboolean initialized;
gpointer dummy[10];
char dummy_checksum_data[65*2];
char dummy_checksum_data[(OSTREE_SHA256_STRING_LEN+1)*2];
};
typedef struct _OstreeRepoCommitTraverseIter OstreeRepoCommitTraverseIter;

View File

@ -65,8 +65,8 @@ _ostree_sysroot_list_deployment_dirs_for_os (GFile *osdir,
g_autofree char *csum = NULL;
gint deployserial;
if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
cancellable, error))
if (!g_file_enumerator_iterate (dir_enum, &file_info, &child,
cancellable, error))
goto out;
if (file_info == NULL)
break;
@ -127,8 +127,8 @@ list_all_deployment_directories (OstreeSysroot *self,
GFileInfo *file_info = NULL;
GFile *child = NULL;
if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
NULL, error))
if (!g_file_enumerator_iterate (dir_enum, &file_info, &child,
NULL, error))
goto out;
if (file_info == NULL)
break;
@ -215,8 +215,8 @@ list_all_boot_directories (OstreeSysroot *self,
GFile *child = NULL;
const char *name;
if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
NULL, error))
if (!g_file_enumerator_iterate (dir_enum, &file_info, &child,
NULL, error))
goto out;
if (file_info == NULL)
break;

View File

@ -473,7 +473,7 @@ merge_etc_changes (GFile *orig_etc,
goto out;
}
gs_log_structured_print_id_v (OSTREE_CONFIGMERGE_ID,
ot_log_structured_print_id_v (OSTREE_CONFIGMERGE_ID,
"Copying /etc changes: %u modified, %u removed, %u added",
modified->len,
removed->len,
@ -773,7 +773,7 @@ selinux_relabel_var_if_needed (OstreeSysroot *sysroot,
if (!g_file_query_exists (deployment_var_labeled, NULL))
{
gs_log_structured_print_id_v (OSTREE_VARRELABEL_ID,
ot_log_structured_print_id_v (OSTREE_VARRELABEL_ID,
"Relabeling /var (no stamp file '%s' found)",
gs_file_get_path_cached (deployment_var_labeled));
@ -1927,7 +1927,7 @@ ostree_sysroot_write_deployments (OstreeSysroot *self,
}
}
gs_log_structured_print_id_v (OSTREE_DEPLOYMENT_COMPLETE_ID,
ot_log_structured_print_id_v (OSTREE_DEPLOYMENT_COMPLETE_ID,
"%s; bootconfig swap: %s deployment count change: %i",
(bootloader_is_atomic ? "Transaction complete" : "Bootloader updated"),
requires_new_bootversion ? "yes" : "no",

View File

@ -493,3 +493,55 @@ ot_util_ensure_directory_and_fsync (GFile *dir,
out:
return ret;
}
#if !GLIB_CHECK_VERSION(2, 44, 0)
gboolean
ot_file_enumerator_iterate (GFileEnumerator *direnum,
GFileInfo **out_info,
GFile **out_child,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GError *temp_error = NULL;
static GQuark cached_info_quark;
static GQuark cached_child_quark;
static gsize quarks_initialized;
g_return_val_if_fail (direnum != NULL, FALSE);
g_return_val_if_fail (out_info != NULL, FALSE);
if (g_once_init_enter (&quarks_initialized))
{
cached_info_quark = g_quark_from_static_string ("ot-cached-info");
cached_child_quark = g_quark_from_static_string ("ot-cached-child");
g_once_init_leave (&quarks_initialized, 1);
}
*out_info = g_file_enumerator_next_file (direnum, cancellable, &temp_error);
if (out_child)
*out_child = NULL;
if (temp_error != NULL)
{
g_propagate_error (error, temp_error);
goto out;
}
else if (*out_info != NULL)
{
g_object_set_qdata_full ((GObject*)direnum, cached_info_quark, *out_info, (GDestroyNotify)g_object_unref);
if (out_child != NULL)
{
const char *name = g_file_info_get_name (*out_info);
*out_child = g_file_get_child (g_file_enumerator_get_container (direnum), name);
g_object_set_qdata_full ((GObject*)direnum, cached_child_quark, *out_child, (GDestroyNotify)g_object_unref);
}
}
ret = TRUE;
out:
return ret;
}
#endif

View File

@ -93,4 +93,26 @@ gboolean ot_util_fsync_directory (GFile *dir,
GCancellable *cancellable,
GError **error);
#if !GLIB_CHECK_VERSION(2, 44, 0)
gboolean
ot_file_enumerator_iterate (GFileEnumerator *direnum,
GFileInfo **out_info,
GFile **out_child,
GCancellable *cancellable,
GError **error);
#else
static inline gboolean
ot_file_enumerator_iterate (GFileEnumerator *direnum,
GFileInfo **out_info,
GFile **out_child,
GCancellable *cancellable,
GError **error)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
return (g_file_enumerator_iterate) (direnum, out_info, out_child, cancellable, error);
G_GNUC_END_IGNORE_DEPRECATIONS;
}
#endif
#define g_file_enumerator_iterate ot_file_enumerator_iterate
G_END_DECLS

View File

@ -0,0 +1,163 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2016 Colin Walters <walters@verbum.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Colin Walters <walters@verbum.org>
*/
#include "config.h"
#include <gio/gio.h>
#include <string.h>
#include "otutil.h"
#include "libglnx.h"
#ifdef HAVE_LIBSYSTEMD
#define SD_JOURNAL_SUPPRESS_LOCATION
#include <systemd/sd-journal.h>
#endif
#include <glib-unix.h>
/**
* ot_log_structured:
* @message: Text message to send
* @keys: (allow-none) (array zero-terminated=1) (element-type utf8): Optional structured data
*
* Log structured data in an operating-system specific fashion. The
* parameter @opts should be an array of UTF-8 KEY=VALUE strings.
* This function does not support binary data. See
* http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html
* for more information about fields that can be used on a systemd
* system.
*/
static void
ot_log_structured (const char *message,
const char *const *keys)
{
#ifdef HAVE_LIBSYSTEMD
const char *const*iter;
g_autofree char *msgkey = NULL;
guint i, n_opts;
struct iovec *iovs;
for (n_opts = 0, iter = keys; *iter; iter++, n_opts++)
;
n_opts++; /* Add one for MESSAGE= */
iovs = g_alloca (sizeof (struct iovec) * n_opts);
for (i = 0, iter = keys; *iter; iter++, i++) {
iovs[i].iov_base = (char*)keys[i];
iovs[i].iov_len = strlen (keys[i]);
}
g_assert(i == n_opts-1);
msgkey = g_strconcat ("MESSAGE=", message, NULL);
iovs[i].iov_base = msgkey;
iovs[i].iov_len = strlen (msgkey);
// The code location isn't useful since we're wrapping
sd_journal_sendv (iovs, n_opts);
#else
g_print ("%s\n", message);
#endif
}
/**
* ot_stdout_is_journal:
*
* Use this function when you want your code to behave differently
* depeneding on whether your program was started as a systemd unit,
* or e.g. interactively at a terminal.
*
* Returns: %TRUE if stdout is (probably) connnected to the systemd journal
*/
static gboolean
ot_stdout_is_journal (void)
{
static gsize initialized;
static gboolean stdout_is_socket;
if (g_once_init_enter (&initialized))
{
guint64 pid = (guint64) getpid ();
g_autofree char *fdpath = g_strdup_printf ("/proc/%" G_GUINT64_FORMAT "/fd/1", pid);
char buf[1024];
ssize_t bytes_read;
if ((bytes_read = readlink (fdpath, buf, sizeof(buf) - 1)) != -1)
{
buf[bytes_read] = '\0';
stdout_is_socket = g_str_has_prefix (buf, "socket:");
}
else
stdout_is_socket = FALSE;
g_once_init_leave (&initialized, TRUE);
}
return stdout_is_socket;
}
/**
* gs_log_structured_print:
* @message: A message to log
* @keys: (allow-none) (array zero-terminated=1) (element-type utf8): Optional structured data
*
* Like gs_log_structured(), but also print to standard output (if it
* is not already connected to the system log).
*/
static void
ot_log_structured_print (const char *message,
const char *const *keys)
{
ot_log_structured (message, keys);
#ifdef HAVE_LIBSYSTEMD
if (!ot_stdout_is_journal ())
g_print ("%s\n", message);
#endif
}
/**
* ot_log_structured_print_id_v:
* @message_id: A unique MESSAGE_ID
* @format: A format string
*
* The provided @message_id is a unique MESSAGE_ID (see <ulink url="http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html"> for more information).
*
* This function otherwise acts as ot_log_structured_print(), taking
* @format as a format string.
*/
void
ot_log_structured_print_id_v (const char *message_id,
const char *format,
...)
{
const char *key0 = glnx_strjoina ("MESSAGE_ID=", message_id);
const char *keys[] = { key0, NULL };
g_autofree char *msg = NULL;
va_list args;
va_start (args, format);
msg = g_strdup_vprintf (format, args);
va_end (args);
ot_log_structured_print (msg, (const char *const *)keys);
}

View File

@ -0,0 +1,31 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2016 Colin Walters <walters@verbum.org>.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#pragma once
#include "ot-unix-utils.h"
G_BEGIN_DECLS
void ot_log_structured_print_id_v (const char *message_id,
const char *format,
...);
G_END_DECLS

View File

@ -47,5 +47,6 @@
#include <ot-spawn-utils.h>
#include <ot-checksum-utils.h>
#include <ot-gpg-utils.h>
#include <ot-log-utils.h>
void ot_ptrarray_add_many (GPtrArray *a, ...) G_GNUC_NULL_TERMINATED;

View File

@ -64,7 +64,7 @@ ot_admin_builtin_switch (int argc, char **argv, GCancellable *cancellable, GErro
GKeyFile *old_origin;
GKeyFile *new_origin = NULL;
context = g_option_context_new ("REF - Construct new tree from current origin and deploy it, if it changed");
context = g_option_context_new ("REF - Construct new tree from REF and deploy it");
if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER,

View File

@ -114,8 +114,8 @@ relabel_recursively (OstreeSePolicy *sepolicy,
GFile *child;
GFileType ftype;
if (!gs_file_enumerator_iterate (direnum, &file_info, &child,
cancellable, error))
if (!g_file_enumerator_iterate (direnum, &file_info, &child,
cancellable, error))
goto out;
if (file_info == NULL)
break;

View File

@ -40,6 +40,7 @@ static gboolean opt_whiteouts;
static gboolean opt_from_stdin;
static char *opt_from_file;
static gboolean opt_disable_fsync;
static gboolean opt_require_hardlinks;
static gboolean
parse_fsync_cb (const char *option_name,
@ -67,6 +68,7 @@ static GOptionEntry options[] = {
{ "from-stdin", 0, 0, G_OPTION_ARG_NONE, &opt_from_stdin, "Process many checkouts from standard input", NULL },
{ "from-file", 0, 0, G_OPTION_ARG_STRING, &opt_from_file, "Process many checkouts from input file", "FILE" },
{ "fsync", 0, 0, G_OPTION_ARG_CALLBACK, parse_fsync_cb, "Specify how to invoke fsync()", "POLICY" },
{ "require-hardlinks", 'H', 0, G_OPTION_ARG_NONE, &opt_require_hardlinks, "Do not fall back to full copies if hardlinking fails", NULL },
{ NULL }
};
@ -85,7 +87,7 @@ process_one_checkout (OstreeRepo *repo,
* `ostree_repo_checkout_tree_at` until such time as we have a more
* convenient infrastructure for testing C APIs with data.
*/
if (opt_disable_cache || opt_whiteouts)
if (opt_disable_cache || opt_whiteouts || opt_require_hardlinks)
{
OstreeRepoCheckoutOptions options = { 0, };
@ -97,6 +99,7 @@ process_one_checkout (OstreeRepo *repo,
options.process_whiteouts = TRUE;
if (subpath)
options.subpath = subpath;
options.no_copy_fallback = opt_require_hardlinks;
if (!ostree_repo_checkout_tree_at (repo, &options,
AT_FDCWD, destination,

View File

@ -428,7 +428,15 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
else if (!opt_orphan)
{
if (!ostree_repo_resolve_rev (repo, opt_branch, TRUE, &parent, error))
goto out;
{
if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY))
{
/* A folder exists with the specified ref name,
* which is handled by _ostree_repo_write_ref */
g_clear_error (error);
}
else goto out;
}
}
if (opt_editor)

View File

@ -72,9 +72,19 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
{
g_autofree char *checksum = NULL;
g_autofree char *checksum_existing = NULL;
g_autofree char *remote = NULL;
g_autofree char *ref = NULL;
if (!ostree_repo_resolve_rev (repo, opt_create, TRUE, &checksum_existing, error))
goto out;
if (!ostree_repo_resolve_rev_ext (repo, opt_create, TRUE, OSTREE_REPO_RESOLVE_REV_EXT_NONE, &checksum_existing, error))
{
if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY))
{
/* A folder exists with the specified ref name,
* which is handled by _ostree_repo_write_ref */
g_clear_error (error);
}
else goto out;
}
if (checksum_existing != NULL)
{
@ -86,7 +96,10 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
if (!ostree_repo_resolve_rev (repo, refspec_prefix, FALSE, &checksum, error))
goto out;
if (!ostree_repo_set_ref_immediate (repo, NULL, opt_create, checksum,
if (!ostree_parse_refspec (opt_create, &remote, &ref, error))
goto out;
if (!ostree_repo_set_ref_immediate (repo, remote, ref, checksum,
cancellable, error))
goto out;
}

View File

@ -37,6 +37,7 @@ static gboolean opt_empty;
static gboolean opt_swap_endianness;
static gboolean opt_inline;
static gboolean opt_disable_bsdiff;
static gboolean opt_if_not_exists;
#define BUILTINPROTO(name) static gboolean ot_static_delta_builtin_ ## name (int argc, char **argv, GCancellable *cancellable, GError **error)
@ -64,6 +65,7 @@ static GOptionEntry generate_options[] = {
{ "inline", 0, 0, G_OPTION_ARG_NONE, &opt_inline, "Inline delta parts into main delta", NULL },
{ "to", 0, 0, G_OPTION_ARG_STRING, &opt_to_rev, "Create delta to revision REV", "REV" },
{ "disable-bsdiff", 0, 0, G_OPTION_ARG_NONE, &opt_disable_bsdiff, "Disable use of bsdiff", NULL },
{ "if-not-exists", 'n', 0, G_OPTION_ARG_NONE, &opt_if_not_exists, "Only generate if a delta does not already exist", NULL },
{ "set-endianness", 0, 0, G_OPTION_ARG_STRING, &opt_endianness, "Choose metadata endianness ('l' or 'B')", "ENDIAN" },
{ "swap-endianness", 0, 0, G_OPTION_ARG_NONE, &opt_swap_endianness, "Swap metadata endianness from host order", NULL },
{ "min-fallback-size", 0, 0, G_OPTION_ARG_STRING, &opt_min_fallback_size, "Minimum uncompressed size in megabytes for individual HTTP request", NULL},
@ -264,6 +266,20 @@ ot_static_delta_builtin_generate (int argc, char **argv, GCancellable *cancellab
}
if (!ostree_repo_resolve_rev (repo, opt_to_rev, FALSE, &to_resolved, error))
goto out;
if (opt_if_not_exists)
{
gboolean does_exist;
g_autofree char *delta_id = from_resolved ? g_strconcat (from_resolved, "-", to_resolved, NULL) : g_strdup (to_resolved);
if (!ostree_cmd__private__ ()->ostree_static_delta_query_exists (repo, delta_id, &does_exist, cancellable, error))
goto out;
if (does_exist)
{
g_print ("Delta %s already exists.\n", delta_id);
ret = TRUE;
goto out;
}
}
if (opt_endianness)
{

View File

@ -38,8 +38,14 @@ static char *opt_log = NULL;
static gboolean opt_daemonize;
static gboolean opt_autoexit;
static gboolean opt_force_ranges;
static int opt_random_500s_percentage;
/* We have a strong upper bound for any unlikely
* cases involving repeated random 500s. */
static int opt_random_500s_max = 100;
static gint opt_port = 0;
static guint emitted_random_500s_count = 0;
typedef struct {
GFile *root;
gboolean running;
@ -52,6 +58,8 @@ 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 },
{ "random-500s", 0, 0, G_OPTION_ARG_INT, &opt_random_500s_percentage, "Generate random HTTP 500 errors approximately for PERCENTAGE requests", "PERCENTAGE" },
{ "random-500s-max", 0, 0, G_OPTION_ARG_INT, &opt_random_500s_max, "Limit HTTP 500 errors to MAX (default 100)", "MAX" },
{ "log-file", 0, 0, G_OPTION_ARG_FILENAME, &opt_log, "Put logs here", "PATH" },
{ NULL }
};
@ -187,6 +195,15 @@ do_get (OtTrivialHttpd *self,
goto out;
}
if (opt_random_500s_percentage > 0 &&
emitted_random_500s_count < opt_random_500s_max &&
g_random_int_range (0, 100) < opt_random_500s_percentage)
{
emitted_random_500s_count++;
soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
goto out;
}
if (path[0] == '/')
path++;
@ -388,6 +405,13 @@ ostree_builtin_trivial_httpd (int argc, char **argv, GCancellable *cancellable,
app->root = g_file_new_for_path (dirpath);
if (!(opt_random_500s_percentage >= 0 && opt_random_500s_percentage <= 99))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid --random-500s=%u", opt_random_500s_percentage);
goto out;
}
if (opt_log)
{
GOutputStream *stream = NULL;

View File

@ -181,7 +181,7 @@ dump_summary_ref (const char *ref_name,
csum_bytes = ostree_checksum_bytes_peek_validate (csum_v, &csum_error);
if (csum_error == NULL)
{
char csum[65];
char csum[OSTREE_SHA256_STRING_LEN+1];
ostree_checksum_inplace_from_bytes (csum_bytes, csum);
g_print (" %s\n", csum);

View File

@ -261,8 +261,11 @@ can_write (const char *path)
else
return -errno;
}
if (!devino_set_contains (stbuf.st_dev, stbuf.st_ino))
return -EROFS;
if (!S_ISDIR (stbuf.st_mode))
{
if (!devino_set_contains (stbuf.st_dev, stbuf.st_ino))
return -EROFS;
}
return 0;
}

View File

@ -94,6 +94,9 @@ ot_test_setup_sysroot (GCancellable *cancellable,
if (!ot_test_run_libtest ("setup_os_repository \"archive-z2\" \"syslinux\"", error))
goto out;
/* Make sure deployments are mutable */
g_setenv ("OSTREE_SYSROOT_DEBUG", "mutable-deployments", TRUE);
ret_sysroot = ostree_sysroot_new (sysroot_path);
ret = TRUE;

View File

@ -138,6 +138,7 @@ assert_file_has_content () {
if ! grep -q -e "$2" "$1"; then
sed -e 's/^/# /' < "$1" >&2
echo 1>&2 "File '$1' doesn't match regexp '$2'"
cat $1
exit 1
fi
}

View File

@ -43,10 +43,9 @@ assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'option
echo "ok deploy with --karg, but same config"
${CMD_PREFIX} ostree admin deploy --karg-proc-cmdline --os=testos testos:testos/buildmaster/x86_64-runtime
# Here we're asserting that the *host* system has a root= kernel
# argument. I think it's unlikely that anyone doesn't have one, but
# if this is not true for you, please file a bug!
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*root=.'
for arg in $(cat /proc/cmdline); do
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf "options.*$arg"
done
echo "ok deploy --karg-proc-cmdline"

View File

@ -54,8 +54,7 @@ assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'option
echo "ok instutil set-kargs --append"
${CMD_PREFIX} ostree admin instutil set-kargs --import-proc-cmdline
# Here we're asserting that the *host* system has a root= kernel
# argument. I think it's unlikely that anyone doesn't have one, but
# if this is not true for you, please file a bug!
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*root=.'
for arg in $(cat /proc/cmdline); do
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf "options.*$arg"
done
echo "ok instutil set-kargs --import-proc-cmdline"

View File

@ -31,30 +31,30 @@ mkdir test
echo hello > test/a
${CMD_PREFIX} $OSTREE commit -b test -s "A commit" test
$OSTREE commit -b test -s "A commit" test
echo "ok commit 1"
${CMD_PREFIX} $OSTREE summary --update
$OSTREE summary --update
OLD_MD5=$(md5sum repo/summary)
echo hello2 > test/a
${CMD_PREFIX} $OSTREE commit -b test -s "Another commit" test
$OSTREE commit -b test -s "Another commit" test
echo "ok commit 2"
assert_streq "$OLD_MD5" "$(md5sum repo/summary)"
${CMD_PREFIX} $OSTREE --repo=repo config set core.commit-update-summary true
$OSTREE --repo=repo config set core.commit-update-summary true
echo hello3 > test/a
${CMD_PREFIX} $OSTREE commit -b test -s "Another commit..." test
$OSTREE commit -b test -s "Another commit..." test
echo "ok commit 3"
assert_not_streq "$OLD_MD5" "$(md5sum repo/summary)"
# Check that summary --update deletes the .sig file
touch repo/summary.sig
${CMD_PREFIX} $OSTREE summary --update
$OSTREE summary --update
assert_not_has_file repo/summary.sig

View File

@ -82,6 +82,8 @@ get_assert_one_direntry_matching() {
origrev=$(${CMD_PREFIX} ostree --repo=repo rev-parse test)
${CMD_PREFIX} ostree --repo=repo static-delta generate --empty --to=${origrev}
${CMD_PREFIX} ostree --repo=repo static-delta generate --if-not-exists --empty --to=${origrev} > out.txt
assert_file_has_content out.txt "${origrev} already exists"
${CMD_PREFIX} ostree --repo=repo static-delta list | grep ${origrev} || exit 1
${CMD_PREFIX} ostree --repo=repo prune
${CMD_PREFIX} ostree --repo=repo static-delta list | grep ${origrev} || exit 1
@ -91,7 +93,12 @@ ${CMD_PREFIX} ostree --repo=repo commit -b test -s test --tree=dir=files
newrev=$(${CMD_PREFIX} ostree --repo=repo rev-parse test)
${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline
${CMD_PREFIX} ostree --repo=repo static-delta generate --if-not-exists --from=${origrev} --to=${newrev} --inline
${CMD_PREFIX} ostree --repo=repo static-delta generate --if-not-exists --from=${origrev} --to=${newrev} --inline > out.txt
assert_file_has_content out.txt "${origrev}-${newrev} already exists"
# Should regenerate
${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline > out.txt
assert_not_file_has_content out.txt "${origrev}-${newrev} already exists"
deltaprefix=$(get_assert_one_direntry_matching repo/deltas '.')
deltadir=$(get_assert_one_direntry_matching repo/deltas/${deltaprefix} '-')

View File

@ -433,6 +433,9 @@ entry_pathname_test_helper (gconstpointer data, gboolean on)
OstreeRepoCommitModifier *modifier = NULL;
gboolean met_etc_file = FALSE;
if (skip_if_no_xattr (td))
goto out;
modifier = ostree_repo_commit_modifier_new (0, NULL, NULL, NULL);
ostree_repo_commit_modifier_set_xattr_callback (modifier, path_cb,
NULL, &met_etc_file);

43
tests/test-pull-repeated.sh Executable file
View File

@ -0,0 +1,43 @@
#!/bin/bash
#
# Copyright (C) 2016 Red Hat
#
# 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.
set -euo pipefail
. $(dirname $0)/libtest.sh
echo "1..1"
COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}"
setup_fake_remote_repo1 "archive-z2" "${COMMIT_SIGN}" --random-500s=50
cd ${test_tmpdir}
${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2
${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
for x in $(seq 200); do
if ${CMD_PREFIX} ostree --repo=repo pull --mirror origin main 2>err.txt; then
echo "Success on iteration ${x}"
break;
fi
assert_file_has_content err.txt "500.*Internal Server Error"
done
${CMD_PREFIX} ostree --repo=repo fsck
${CMD_PREFIX} ostree --repo=repo rev-parse main
echo "ok repeated pull after 500s"

View File

@ -23,16 +23,18 @@ set -euo pipefail
setup_fake_remote_repo1 "archive-z2"
echo '1..1'
echo '1..2'
repopath=${test_tmpdir}/ostree-srv/gnomerepo
cp -a ${repopath} ${repopath}.orig
for remoteurl in $(cat httpd-address)/ostree/gnomerepo \
file://$(pwd)/ostree-srv/gnomerepo; do
cd ${test_tmpdir}
rm repo -rf
mkdir repo
${CMD_PREFIX} ostree --repo=repo init
${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin ${remoteurl}
${CMD_PREFIX} ostree --repo=repo pull --subpath=/baz origin main
@ -51,5 +53,5 @@ ${CMD_PREFIX} ostree --repo=repo ls origin:main /firstfile
${CMD_PREFIX} ostree --repo=repo pull origin main
assert_not_has_file repo/state/${rev}.commitpartial
${CMD_PREFIX} ostree --repo=repo fsck
echo "ok"
done

View File

@ -92,8 +92,28 @@ fi
${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create1
assert_file_has_content refscount.create1 "^5$"
${CMD_PREFIX} ostree --repo=repo refs ctest --create ctest-new
${CMD_PREFIX} ostree --repo=repo refs ctest --create=ctest-new
${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create2
assert_file_has_content refscount.create2 "^6$"
#Check to see if a deleted folder can be re-used as the name of a ref
${CMD_PREFIX} ostree --repo=repo refs foo/ctest --delete
${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create3
assert_file_has_content refscount.create3 "^5$"
${CMD_PREFIX} ostree --repo=repo refs ctest --create=foo
${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create4
assert_file_has_content refscount.create4 "^6$"
#Check if a name for a ref in remote repo can be used locally, and vice versa.
${CMD_PREFIX} ostree --repo=repo commit --branch=origin:remote1
${CMD_PREFIX} ostree --repo=repo commit --branch=local1
${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create5
assert_file_has_content refscount.create5 "^8$"
${CMD_PREFIX} ostree --repo=repo refs origin:remote1 --create=remote1
${CMD_PREFIX} ostree --repo=repo refs origin:remote1 --create=origin/remote1
${CMD_PREFIX} ostree --repo=repo refs local1 --create=origin:local1
${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create6
assert_file_has_content refscount.create6 "^11$"
echo "ok refs"

View File

@ -26,7 +26,7 @@ skip_without_user_xattrs
setup_test_repository "bare-user"
echo "1..5"
echo "1..6"
mkdir mnt
@ -71,3 +71,13 @@ echo "ok deletion"
${CMD_PREFIX} ostree --repo=repo commit -b test2 -s fromfuse --link-checkout-speedup --tree=dir=checkout-test2
echo "ok commit"
${CMD_PREFIX} ostree --repo=repo checkout -U test2 mnt/test2-checkout-copy-fallback
assert_file_has_content mnt/test2-checkout-copy-fallback/anewfile-for-fuse anewfile-for-fuse
if ${CMD_PREFIX} ostree --repo=repo checkout -UH test2 mnt/test2-checkout-copy-hardlinked 2>err.txt; then
assert_not_reached "Checking out via hardlinks across mountpoint unexpectedly succeeded!"
fi
assert_file_has_content err.txt "Invalid cross-device link"
echo "ok checkout copy fallback"