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 if BUILDOPT_SYSTEMD
systemdsystemunit_DATA = src/boot/ostree-prepare-root.service \ systemdsystemunit_DATA = src/boot/ostree-prepare-root.service \
src/boot/ostree-remount.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 endif
if !BUILDOPT_BUILTIN_GRUB2_MKCONFIG 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' -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_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) 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 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) libostree_1_la_LIBADD += $(OT_DEP_LIBARCHIVE_LIBS)
endif endif
if BUILDOPT_LIBSYSTEMD
libostree_1_la_CFLAGS += $(LIBSYSTEMD_CFLAGS)
libostree_1_la_LIBADD += $(LIBSYSTEMD_LIBS)
endif
if USE_LIBSOUP if USE_LIBSOUP
libostree_1_la_SOURCES += \ libostree_1_la_SOURCES += \
src/libostree/ostree-fetcher.h \ 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_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_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 if USE_LIBSOUP
ostree_SOURCES += \ ostree_SOURCES += \

View File

@ -36,6 +36,8 @@ libotutil_la_SOURCES = \
src/libotutil/ot-variant-utils.h \ src/libotutil/ot-variant-utils.h \
src/libotutil/ot-gio-utils.c \ src/libotutil/ot-gio-utils.c \
src/libotutil/ot-gio-utils.h \ 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.c \
src/libotutil/ot-gpg-utils.h \ src/libotutil/ot-gpg-utils.h \
src/libotutil/otutil.c \ src/libotutil/otutil.c \
@ -43,5 +45,5 @@ libotutil_la_SOURCES = \
src/libotutil/ot-tool-util.c \ src/libotutil/ot-tool-util.c \
src/libotutil/ot-tool-util.h \ src/libotutil/ot-tool-util.h \
$(NULL) $(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_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) 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-metalink.sh \
tests/test-pull-summary-sigs.sh \ tests/test-pull-summary-sigs.sh \
tests/test-pull-resume.sh \ tests/test-pull-resume.sh \
tests/test-pull-repeated.sh \
tests/test-pull-untrusted.sh \ tests/test-pull-untrusted.sh \
tests/test-pull-override-url.sh \ tests/test-pull-override-url.sh \
tests/test-local-pull.sh \ tests/test-local-pull.sh \
@ -232,12 +233,7 @@ EXTRA_DIST += \
tests/libostreetest.h \ tests/libostreetest.h \
tests/libtest.sh \ tests/libtest.sh \
tests/gpg-verify-data/README.md \ tests/gpg-verify-data/README.md \
tests/gpg-verify-data/lgpl2 \ $(NULL)
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
tests/libreaddir-rand.so: Makefile tests/libreaddir-rand.so: Makefile
$(AM_V_GEN) ln -fns ../.libs/libreaddir-rand.so tests $(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 CLEANFILES += tests/libreaddir-rand.so tests/ostree-symlink-stamp tests/ostree
tests/ostree-symlink-stamp: Makefile 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; \ ln -sf "$${real_bin}" tests/ostree; \
touch $@ touch $@

View File

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

View File

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

View File

@ -1,5 +1,5 @@
AC_PREREQ([2.63]) 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_HEADER([config.h])
AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_MACRO_DIR([buildutil])
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
@ -17,7 +17,7 @@ AC_PROG_YACC
changequote(,)dnl changequote(,)dnl
if test "x$GCC" = "xyes"; then 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=implicit-function-declaration \
-Werror=pointer-arith -Werror=init-self -Werror=format=2 \ -Werror=pointer-arith -Werror=init-self -Werror=format=2 \
-Werror=format-security \ -Werror=format-security \
@ -251,7 +251,13 @@ AC_ARG_WITH(mkinitcpio,
[with_mkinitcpio=no]) [with_mkinitcpio=no])
AM_CONDITIONAL(BUILDOPT_MKINITCPIO, test x$with_mkinitcpio = xyes) 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 with_systemd=yes
AC_ARG_WITH([systemdsystemunitdir], AC_ARG_WITH([systemdsystemunitdir],
AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
@ -309,6 +315,7 @@ echo "
libsoup (retrieve remote HTTP repositories): $with_soup libsoup (retrieve remote HTTP repositories): $with_soup
libsoup TLS client certs: $have_libsoup_client_certs libsoup TLS client certs: $have_libsoup_client_certs
SELinux: $with_selinux SELinux: $with_selinux
systemd: $have_libsystemd
libmount: $with_libmount libmount: $with_libmount
libarchive (parse tar files directly): $with_libarchive libarchive (parse tar files directly): $with_libarchive
static deltas: yes (always enabled now) 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" echo " grub2-mkconfig path: $GRUB2_MKCONFIG"
]) ])
AS_IF([test "x$with_systemd" = "xyes"], [
echo " systemd unit dir: $with_systemdsystemunitdir"
])
echo "" 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. 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 The need to make and distribute snapshots for this system was the original
inspiration for ostree. 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; ostree_repo_remote_fetch_summary_with_options;
} LIBOSTREE_2016.5; } LIBOSTREE_2016.5;
LIBOSTREE_2016.7 {
global:
ostree_repo_resolve_rev_ext;
} LIBOSTREE_2016.6;
/* NOTE NOTE NOTE /* NOTE NOTE NOTE
* Versions above here are released. Only add symbols below this line. * Versions above here are released. Only add symbols below this line.
* NOTE NOTE NOTE * NOTE NOTE NOTE
*/ */
/* Uncomment this when adding a new symbol */ /* UNCOMMENT WHEN ADDING THE FIRST NEW SYMBOL FOR 2016.8
/*
LIBOSTREE_2016.7 { LIBOSTREE_2016.7 {
global: global:
ostree_some_new_symbol; insert_symbol_here;
} LIBOSTREE_2016.6; } LIBOSTREE_2016.8;
*/ */

View File

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

View File

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

View File

@ -27,6 +27,7 @@ G_BEGIN_DECLS
typedef struct { typedef struct {
gboolean (* ostree_generate_grub2_config) (OstreeSysroot *sysroot, int bootversion, int target_fd, GCancellable *cancellable, GError **error); 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_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); gboolean (* ostree_static_delta_delete) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error);
} OstreeCmdPrivateVTable; } OstreeCmdPrivateVTable;

View File

@ -128,13 +128,6 @@ _ostree_loose_path (char *buf,
OstreeObjectType objtype, OstreeObjectType objtype,
OstreeRepoMode repo_mode); 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_NAME "ostree.gpgsigs"
#define _OSTREE_METADATA_GPGSIGS_TYPE G_VARIANT_TYPE ("aay") #define _OSTREE_METADATA_GPGSIGS_TYPE G_VARIANT_TYPE ("aay")

View File

@ -1047,6 +1047,8 @@ ostree_object_type_to_string (OstreeObjectType objtype)
return "commit"; return "commit";
case OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT: case OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT:
return "tombstone-commit"; return "tombstone-commit";
case OSTREE_OBJECT_TYPE_COMMIT_META:
return "commitmeta";
default: default:
g_assert_not_reached (); g_assert_not_reached ();
return NULL; return NULL;
@ -1070,6 +1072,10 @@ ostree_object_type_from_string (const char *str)
return OSTREE_OBJECT_TYPE_DIR_META; return OSTREE_OBJECT_TYPE_DIR_META;
else if (!strcmp (str, "commit")) else if (!strcmp (str, "commit"))
return OSTREE_OBJECT_TYPE_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 (); g_assert_not_reached ();
return 0; return 0;
} }
@ -1269,7 +1275,7 @@ ostree_checksum_to_bytes_v (const char *checksum)
/** /**
* ostree_checksum_inplace_from_bytes: (skip) * ostree_checksum_inplace_from_bytes: (skip)
* @csum: (array fixed-size=32): An binary checksum of length 32 * @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. * Overwrite the contents of @buf with stringified version of @csum.
*/ */
@ -1340,7 +1346,7 @@ ostree_checksum_b64_inplace_from_bytes (const guchar *csum,
char * char *
ostree_checksum_from_bytes (const guchar *csum) 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); ostree_checksum_inplace_from_bytes (csum, ret);
return ret; return ret;
} }
@ -1414,7 +1420,13 @@ _ostree_loose_path (char *buf,
OstreeObjectType objtype, OstreeObjectType objtype,
OstreeRepoMode mode) 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; 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: * _ostree_get_relative_object_path:
* @checksum: ASCII checksum string * @checksum: ASCII checksum string
@ -1484,7 +1469,7 @@ _ostree_get_relative_object_path (const char *checksum,
{ {
GString *path; GString *path;
g_assert (strlen (checksum) == 64); g_assert (strlen (checksum) == OSTREE_SHA256_STRING_LEN);
path = g_string_new ("objects/"); path = g_string_new ("objects/");
@ -1759,7 +1744,7 @@ ostree_validate_structureof_checksum_string (const char *checksum,
int i = 0; int i = 0;
size_t len = strlen (checksum); 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, g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid rev '%s'", checksum); "Invalid rev '%s'", checksum);
@ -1994,7 +1979,8 @@ ostree_validate_structureof_dirmeta (GVariant *dirmeta,
* ostree_commit_get_parent: * ostree_commit_get_parent:
* @commit_variant: Variant of type %OSTREE_OBJECT_TYPE_COMMIT * @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 * gchar *
ostree_commit_get_parent (GVariant *commit_variant) ostree_commit_get_parent (GVariant *commit_variant)

View File

@ -51,8 +51,20 @@ G_BEGIN_DECLS
*/ */
#define OSTREE_MAX_RECURSION (256) #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) #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: * OstreeObjectType:
* @OSTREE_OBJECT_TYPE_FILE: Content; regular file, symbolic link * @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_DIR_META: Directory metadata
* @OSTREE_OBJECT_TYPE_COMMIT: Toplevel object, refers to tree and dirmeta for root * @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_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 * Enumeration for core object types; %OSTREE_OBJECT_TYPE_FILE is for
* content, the other types are metadata. * content, the other types are metadata.
@ -70,6 +83,7 @@ typedef enum {
OSTREE_OBJECT_TYPE_DIR_META = 3, /* .dirmeta */ OSTREE_OBJECT_TYPE_DIR_META = 3, /* .dirmeta */
OSTREE_OBJECT_TYPE_COMMIT = 4, /* .commit */ OSTREE_OBJECT_TYPE_COMMIT = 4, /* .commit */
OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT = 5, /* .commit-tombstone */ OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT = 5, /* .commit-tombstone */
OSTREE_OBJECT_TYPE_COMMIT_META = 6, /* .commitmeta */
} OstreeObjectType; } OstreeObjectType;
/** /**
@ -78,14 +92,14 @@ typedef enum {
* *
* Returns: %TRUE if object type is metadata * 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: * OSTREE_OBJECT_TYPE_LAST:
* *
* Last valid object type; use this to validate ranges. * 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: * OSTREE_DIRMETA_GVARIANT_FORMAT:

View File

@ -44,7 +44,7 @@ typedef enum {
typedef struct { typedef struct {
volatile int ref_count; volatile int ref_count;
SoupSession *session; SoupSession *session; /* not referenced */
GMainContext *main_context; GMainContext *main_context;
GMainLoop *main_loop; GMainLoop *main_loop;
@ -88,8 +88,6 @@ typedef struct {
guint64 max_size; guint64 max_size;
guint64 current_size; guint64 current_size;
guint64 content_length; guint64 content_length;
GTask *task;
} OstreeFetcherPendingURI; } OstreeFetcherPendingURI;
/* Used by session_thread_idle_add() */ /* 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)) 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_context, g_main_context_unref);
g_clear_pointer (&thread_closure->main_loop, g_main_loop_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); g_free (thread_closure->tmpdir_name);
glnx_release_lock_file (&thread_closure->tmpdir_lock); 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_clear_pointer (&thread_closure->output_stream_set, g_hash_table_unref);
g_mutex_clear (&thread_closure->output_stream_set_lock); g_mutex_clear (&thread_closure->output_stream_set_lock);
@ -452,13 +446,15 @@ static gpointer
ostree_fetcher_session_thread (gpointer data) ostree_fetcher_session_thread (gpointer data)
{ {
ThreadClosure *closure = data; ThreadClosure *closure = data;
g_autoptr(GMainContext) mainctx = g_main_context_ref (closure->main_context);
gint max_conns; gint max_conns;
/* This becomes the GMainContext that SoupSession schedules async /* This becomes the GMainContext that SoupSession schedules async
* callbacks and emits signals from. Make it the thread-default * callbacks and emits signals from. Make it the thread-default
* context for this thread before creating the session. */ * 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 ", closure->session = soup_session_async_new_with_options (SOUP_SESSION_USER_AGENT, "ostree ",
SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
SOUP_SESSION_USE_THREAD_CONTEXT, 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_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); 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; return NULL;
} }

View File

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

View File

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

View File

@ -1173,43 +1173,31 @@ rename_pending_loose_objects (OstreeRepo *self,
GError **error) GError **error)
{ {
gboolean ret = FALSE; 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; goto out;
/* Iterate over the outer checksum dir */ /* Iterate over the outer checksum dir */
while (TRUE) while (TRUE)
{ {
struct dirent *dent; struct dirent *dent;
gs_dirfd_iterator_cleanup GSDirFdIterator child_dfd_iter = { 0, }; g_auto(GLnxDirFdIterator) child_dfd_iter = { 0, };
struct stat stbuf;
int res;
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; goto out;
if (dent == NULL) if (dent == NULL)
break; break;
do if (dent->d_type != DT_DIR)
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))
continue; continue;
/* All object directories only have two character entries */ /* All object directories only have two character entries */
if (strlen (dent->d_name) != 2) if (strlen (dent->d_name) != 2)
continue; continue;
if (!gs_dirfd_iterator_init_at (dfd_iter.fd, dent->d_name, FALSE, if (!glnx_dirfd_iterator_init_at (dfd_iter.fd, dent->d_name, FALSE,
&child_dfd_iter, error)) &child_dfd_iter, error))
goto out; goto out;
/* Iterate over inner checksum dir */ /* Iterate over inner checksum dir */
@ -1218,9 +1206,8 @@ rename_pending_loose_objects (OstreeRepo *self,
struct dirent *child_dent; struct dirent *child_dent;
char loose_objpath[_OSTREE_LOOSE_PATH_MAX]; 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; goto out;
if (child_dent == NULL) if (child_dent == NULL)
break; break;
@ -2071,8 +2058,7 @@ _ostree_repo_get_commit_metadata_loose_path (OstreeRepo *self,
const char *checksum) const char *checksum)
{ {
char buf[_OSTREE_LOOSE_PATH_MAX]; char buf[_OSTREE_LOOSE_PATH_MAX];
_ostree_loose_path_with_suffix (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT, self->mode, _ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode);
"meta");
return g_file_resolve_relative_path (self->objects_dir, buf); return g_file_resolve_relative_path (self->objects_dir, buf);
} }
@ -2412,7 +2398,7 @@ write_directory_to_mtree_internal (OstreeRepo *self,
GError **error); GError **error);
static gboolean static gboolean
write_dfd_iter_to_mtree_internal (OstreeRepo *self, write_dfd_iter_to_mtree_internal (OstreeRepo *self,
GSDirFdIterator *src_dfd_iter, GLnxDirFdIterator *src_dfd_iter,
OstreeMutableTree *mtree, OstreeMutableTree *mtree,
OstreeRepoCommitModifier *modifier, OstreeRepoCommitModifier *modifier,
GPtrArray *path, GPtrArray *path,
@ -2423,7 +2409,7 @@ static gboolean
write_directory_content_to_mtree_internal (OstreeRepo *self, write_directory_content_to_mtree_internal (OstreeRepo *self,
OstreeRepoFile *repo_dir, OstreeRepoFile *repo_dir,
GFileEnumerator *dir_enum, GFileEnumerator *dir_enum,
GSDirFdIterator *dfd_iter, GLnxDirFdIterator *dfd_iter,
GFileInfo *child_info, GFileInfo *child_info,
OstreeMutableTree *mtree, OstreeMutableTree *mtree,
OstreeRepoCommitModifier *modifier, OstreeRepoCommitModifier *modifier,
@ -2488,9 +2474,9 @@ write_directory_content_to_mtree_internal (OstreeRepo *self,
} }
else 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; goto out;
if (!write_dfd_iter_to_mtree_internal (self, &child_dfd_iter, child_mtree, 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; GFileInfo *child_info;
if (!gs_file_enumerator_iterate (dir_enum, &child_info, NULL, if (!g_file_enumerator_iterate (dir_enum, &child_info, NULL,
cancellable, error)) cancellable, error))
goto out; goto out;
if (child_info == NULL) if (child_info == NULL)
break; break;
@ -2693,7 +2679,7 @@ write_directory_to_mtree_internal (OstreeRepo *self,
static gboolean static gboolean
write_dfd_iter_to_mtree_internal (OstreeRepo *self, write_dfd_iter_to_mtree_internal (OstreeRepo *self,
GSDirFdIterator *src_dfd_iter, GLnxDirFdIterator *src_dfd_iter,
OstreeMutableTree *mtree, OstreeMutableTree *mtree,
OstreeRepoCommitModifier *modifier, OstreeRepoCommitModifier *modifier,
GPtrArray *path, GPtrArray *path,
@ -2760,9 +2746,8 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self,
g_autoptr(GFileInfo) child_info = NULL; g_autoptr(GFileInfo) child_info = NULL;
const char *loose_checksum; 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; goto out;
if (dent == NULL) if (dent == NULL)
break; break;
@ -2888,15 +2873,14 @@ ostree_repo_write_dfd_to_mtree (OstreeRepo *self,
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
g_autoptr(GPtrArray) pathbuilder = NULL; 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) if (modifier && modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES)
self->generate_sizes = TRUE; self->generate_sizes = TRUE;
pathbuilder = g_ptr_array_new (); pathbuilder = g_ptr_array_new ();
if (!gs_dirfd_iterator_init_at (dfd, path, FALSE, if (!glnx_dirfd_iterator_init_at (dfd, path, FALSE, &dfd_iter, error))
&dfd_iter, error))
goto out; goto out;
if (!write_dfd_iter_to_mtree_internal (self, &dfd_iter, mtree, modifier, pathbuilder, 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(GHashTable) dir_contents_checksums = NULL;
g_autoptr(GVariant) serialized_tree = NULL; g_autoptr(GVariant) serialized_tree = NULL;
g_autofree guchar *contents_csum = 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, dir_contents_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, (GDestroyNotify)g_free); (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 (repo != NULL, NULL);
g_return_val_if_fail (contents_checksum != 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 (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 = g_object_new (OSTREE_TYPE_REPO_FILE, NULL);
self->repo = g_object_ref (repo); 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) commit_v = NULL;
g_autoptr(GVariant) tree_contents_csum_v = NULL; g_autoptr(GVariant) tree_contents_csum_v = NULL;
g_autoptr(GVariant) tree_metadata_csum_v = NULL; g_autoptr(GVariant) tree_metadata_csum_v = NULL;
char tree_contents_csum[65]; char tree_contents_csum[OSTREE_SHA256_STRING_LEN + 1];
char tree_metadata_csum[65]; char tree_metadata_csum[OSTREE_SHA256_STRING_LEN + 1];
g_return_val_if_fail (repo != NULL, NULL); g_return_val_if_fail (repo != NULL, NULL);
g_return_val_if_fail (commit != 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, if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
commit, &commit_v, error)) 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) dirs_variant = NULL;
g_autoptr(GVariant) content_csum_v = NULL; g_autoptr(GVariant) content_csum_v = NULL;
g_autoptr(GVariant) meta_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; GFileAttributeMatcher *matcher = NULL;
if (!ostree_repo_file_ensure_resolved (self, error)) if (!ostree_repo_file_ensure_resolved (self, error))

View File

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

View File

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

View File

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

View File

@ -100,14 +100,51 @@ write_checksum_file_at (OstreeRepo *self,
{ {
size_t l = strlen (sha256); size_t l = strlen (sha256);
char *bufnl = alloca (l + 2); char *bufnl = alloca (l + 2);
g_autoptr(GError) temp_error = NULL;
memcpy (bufnl, sha256, l); memcpy (bufnl, sha256, l);
bufnl[l] = '\n'; bufnl[l] = '\n';
bufnl[l+1] = '\0'; bufnl[l+1] = '\0';
if (!_ostree_repo_file_replace_contents (self, dfd, name, (guint8*)bufnl, l + 1, if (!_ostree_repo_file_replace_contents (self, dfd, name, (guint8*)bufnl, l + 1,
cancellable, error)) cancellable, &temp_error))
goto out; {
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; ret = TRUE;
@ -162,6 +199,7 @@ resolve_refspec (OstreeRepo *self,
const char *remote, const char *remote,
const char *ref, const char *ref,
gboolean allow_noent, gboolean allow_noent,
gboolean fallback_remote,
char **out_rev, char **out_rev,
GError **error); GError **error);
@ -170,6 +208,7 @@ resolve_refspec_fallback (OstreeRepo *self,
const char *remote, const char *remote,
const char *ref, const char *ref,
gboolean allow_noent, gboolean allow_noent,
gboolean fallback_remote,
char **out_rev, char **out_rev,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
@ -179,8 +218,8 @@ resolve_refspec_fallback (OstreeRepo *self,
if (self->parent_repo) if (self->parent_repo)
{ {
if (!resolve_refspec (self->parent_repo, remote, ref, if (!resolve_refspec (self->parent_repo, remote, ref, allow_noent,
allow_noent, &ret_rev, error)) fallback_remote, &ret_rev, error))
goto out; goto out;
} }
else if (!allow_noent) else if (!allow_noent)
@ -204,6 +243,7 @@ resolve_refspec (OstreeRepo *self,
const char *remote, const char *remote,
const char *ref, const char *ref,
gboolean allow_noent, gboolean allow_noent,
gboolean fallback_remote,
char **out_rev, char **out_rev,
GError **error) GError **error)
{ {
@ -233,7 +273,7 @@ resolve_refspec (OstreeRepo *self,
if (!ot_openat_ignore_enoent (self->repo_dir_fd, local_ref, &target_fd, error)) if (!ot_openat_ignore_enoent (self->repo_dir_fd, local_ref, &target_fd, error))
goto out; goto out;
if (target_fd == -1) if (target_fd == -1 && fallback_remote)
{ {
local_ref = glnx_strjoina ("refs/remotes/", ref); local_ref = glnx_strjoina ("refs/remotes/", ref);
@ -263,7 +303,7 @@ resolve_refspec (OstreeRepo *self,
} }
else 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)) &ret_rev, cancellable, error))
goto out; goto out;
} }
@ -304,10 +344,10 @@ ostree_repo_resolve_partial_checksum (OstreeRepo *self,
g_return_val_if_fail (error == NULL || *error == NULL, FALSE); 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 */ don't bother looking for it as an object */
off = strspn (refspec, hexchars); off = strspn (refspec, hexchars);
if (off > 64 || refspec[off] != '\0') if (off > OSTREE_SHA256_STRING_LEN || refspec[off] != '\0')
return TRUE; return TRUE;
/* this looks through all objects and adds them to the ref_list if: /* 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; return ret;
} }
/** static gboolean
* ostree_repo_resolve_rev: _ostree_repo_resolve_rev_internal (OstreeRepo *self,
* @self: Repo const char *refspec,
* @refspec: A refspec gboolean allow_noent,
* @allow_noent: Do not throw an error if refspec does not exist gboolean fallback_remote,
* @out_rev: (out) (transfer full): A checksum,or %NULL if @allow_noent is true and it does not exist char **out_rev,
* @error: Error GError **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)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
g_autofree char *ret_rev = NULL; g_autofree char *ret_rev = NULL;
@ -419,7 +449,7 @@ ostree_repo_resolve_rev (OstreeRepo *self,
goto out; goto out;
if (!resolve_refspec (self, remote, ref, allow_noent, if (!resolve_refspec (self, remote, ref, allow_noent,
&ret_rev, error)) fallback_remote, &ret_rev, error))
goto out; goto out;
} }
} }
@ -430,6 +460,53 @@ ostree_repo_resolve_rev (OstreeRepo *self,
return ret; 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 static gboolean
enumerate_refs_recurse (OstreeRepo *repo, enumerate_refs_recurse (OstreeRepo *repo,
const char *remote, const char *remote,
@ -703,7 +780,7 @@ ostree_repo_remote_list_refs (OstreeRepo *self,
{ {
const char *ref_name = NULL; const char *ref_name = NULL;
g_autoptr(GVariant) csum_v = 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); g_variant_get_child (child, 0, "&s", &ref_name);
@ -772,8 +849,10 @@ _ostree_repo_write_ref (OstreeRepo *self,
goto out; 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); g_prefix_error (error, "Opening remotes/ dir %s: ", remote);
goto out; goto out;
} }
@ -781,13 +860,16 @@ _ostree_repo_write_ref (OstreeRepo *self,
if (rev == NULL) if (rev == NULL)
{ {
if (unlinkat (dfd, ref, 0) != 0) if (dfd >= 0)
{ {
if (errno != ENOENT) if (unlinkat (dfd, ref, 0) != 0)
{ {
glnx_set_error_from_errno (error); if (errno != ENOENT)
goto out; {
} glnx_set_error_from_errno (error);
goto out;
}
}
} }
} }
else else

View File

@ -94,8 +94,8 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
GFileInfo *file_info; GFileInfo *file_info;
GFile *child; GFile *child;
if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child, if (!g_file_enumerator_iterate (dir_enum, &file_info, &child,
NULL, error)) NULL, error))
goto out; goto out;
if (file_info == NULL) if (file_info == NULL)
break; break;
@ -117,8 +117,8 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
const char *name1; const char *name1;
const char *name2; const char *name2;
if (!gs_file_enumerator_iterate (dir_enum2, &file_info2, &child2, if (!g_file_enumerator_iterate (dir_enum2, &file_info2, &child2,
NULL, error)) NULL, error))
goto out; goto out;
if (file_info2 == NULL) if (file_info2 == NULL)
break; break;
@ -136,7 +136,7 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
{ {
g_autofree char *buf = g_strconcat (name1, name2, NULL); g_autofree char *buf = g_strconcat (name1, name2, NULL);
GString *out = g_string_new (""); GString *out = g_string_new ("");
char checksum[65]; char checksum[OSTREE_SHA256_STRING_LEN+1];
guchar csum[OSTREE_SHA256_DIGEST_LEN]; guchar csum[OSTREE_SHA256_DIGEST_LEN];
const char *dash = strchr (buf, '-'); const char *dash = strchr (buf, '-');
@ -187,7 +187,7 @@ _ostree_repo_static_delta_part_have_all_objects (OstreeRepo *repo,
{ {
guint8 objtype = *checksums_data; guint8 objtype = *checksums_data;
const guint8 *csum = checksums_data + 1; 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))) if (G_UNLIKELY(!ostree_validate_structureof_objtype (objtype, error)))
goto out; goto out;
@ -354,7 +354,7 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self,
guint64 size; guint64 size;
guint64 usize; guint64 usize;
const guchar *csum; const guchar *csum;
char checksum[65]; char checksum[OSTREE_SHA256_STRING_LEN+1];
gboolean have_all; gboolean have_all;
g_autoptr(GInputStream) part_in = NULL; g_autoptr(GInputStream) part_in = NULL;
g_autoptr(GBytes) delta_data = NULL; g_autoptr(GBytes) delta_data = NULL;
@ -819,6 +819,38 @@ _ostree_repo_static_delta_delete (OstreeRepo *self,
return ret; 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 gboolean
_ostree_repo_static_delta_dump (OstreeRepo *self, _ostree_repo_static_delta_dump (OstreeRepo *self,
const char *delta_id, const char *delta_id,

View File

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

View File

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

View File

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

View File

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

View File

@ -382,6 +382,22 @@ gboolean ostree_repo_resolve_rev (OstreeRepo *self,
char **out_rev, char **out_rev,
GError **error); 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 _OSTREE_PUBLIC
gboolean ostree_repo_list_refs (OstreeRepo *self, gboolean ostree_repo_list_refs (OstreeRepo *self,
const char *refspec_prefix, const char *refspec_prefix,
@ -734,7 +750,8 @@ typedef struct {
guint enable_uncompressed_cache : 1; guint enable_uncompressed_cache : 1;
guint disable_fsync : 1; guint disable_fsync : 1;
guint process_whiteouts : 1; guint process_whiteouts : 1;
guint reserved : 29; guint no_copy_fallback : 1;
guint reserved : 28;
const char *subpath; const char *subpath;
@ -866,7 +883,7 @@ gboolean ostree_repo_traverse_commit_union (OstreeRepo *repo,
struct _OstreeRepoCommitTraverseIter { struct _OstreeRepoCommitTraverseIter {
gboolean initialized; gboolean initialized;
gpointer dummy[10]; gpointer dummy[10];
char dummy_checksum_data[65*2]; char dummy_checksum_data[(OSTREE_SHA256_STRING_LEN+1)*2];
}; };
typedef struct _OstreeRepoCommitTraverseIter OstreeRepoCommitTraverseIter; typedef struct _OstreeRepoCommitTraverseIter OstreeRepoCommitTraverseIter;

View File

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

View File

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

View File

@ -493,3 +493,55 @@ ot_util_ensure_directory_and_fsync (GFile *dir,
out: out:
return ret; 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, GCancellable *cancellable,
GError **error); 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 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-spawn-utils.h>
#include <ot-checksum-utils.h> #include <ot-checksum-utils.h>
#include <ot-gpg-utils.h> #include <ot-gpg-utils.h>
#include <ot-log-utils.h>
void ot_ptrarray_add_many (GPtrArray *a, ...) G_GNUC_NULL_TERMINATED; 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 *old_origin;
GKeyFile *new_origin = NULL; 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, if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER, OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER,

View File

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

View File

@ -40,6 +40,7 @@ static gboolean opt_whiteouts;
static gboolean opt_from_stdin; static gboolean opt_from_stdin;
static char *opt_from_file; static char *opt_from_file;
static gboolean opt_disable_fsync; static gboolean opt_disable_fsync;
static gboolean opt_require_hardlinks;
static gboolean static gboolean
parse_fsync_cb (const char *option_name, 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-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" }, { "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" }, { "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 } { NULL }
}; };
@ -85,7 +87,7 @@ process_one_checkout (OstreeRepo *repo,
* `ostree_repo_checkout_tree_at` until such time as we have a more * `ostree_repo_checkout_tree_at` until such time as we have a more
* convenient infrastructure for testing C APIs with data. * 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, }; OstreeRepoCheckoutOptions options = { 0, };
@ -97,6 +99,7 @@ process_one_checkout (OstreeRepo *repo,
options.process_whiteouts = TRUE; options.process_whiteouts = TRUE;
if (subpath) if (subpath)
options.subpath = subpath; options.subpath = subpath;
options.no_copy_fallback = opt_require_hardlinks;
if (!ostree_repo_checkout_tree_at (repo, &options, if (!ostree_repo_checkout_tree_at (repo, &options,
AT_FDCWD, destination, AT_FDCWD, destination,

View File

@ -428,7 +428,15 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
else if (!opt_orphan) else if (!opt_orphan)
{ {
if (!ostree_repo_resolve_rev (repo, opt_branch, TRUE, &parent, error)) 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) 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 = NULL;
g_autofree char *checksum_existing = 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)) if (!ostree_repo_resolve_rev_ext (repo, opt_create, TRUE, OSTREE_REPO_RESOLVE_REV_EXT_NONE, &checksum_existing, 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 (checksum_existing != NULL) 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)) if (!ostree_repo_resolve_rev (repo, refspec_prefix, FALSE, &checksum, error))
goto out; 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)) cancellable, error))
goto out; goto out;
} }

View File

@ -37,6 +37,7 @@ static gboolean opt_empty;
static gboolean opt_swap_endianness; static gboolean opt_swap_endianness;
static gboolean opt_inline; static gboolean opt_inline;
static gboolean opt_disable_bsdiff; 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) #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 }, { "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" }, { "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 }, { "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" }, { "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 }, { "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}, { "min-fallback-size", 0, 0, G_OPTION_ARG_STRING, &opt_min_fallback_size, "Minimum uncompressed size in megabytes for individual HTTP request", NULL},
@ -265,6 +267,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)) if (!ostree_repo_resolve_rev (repo, opt_to_rev, FALSE, &to_resolved, error))
goto out; 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) if (opt_endianness)
{ {
if (strcmp (opt_endianness, "l") == 0) if (strcmp (opt_endianness, "l") == 0)

View File

@ -38,8 +38,14 @@ static char *opt_log = NULL;
static gboolean opt_daemonize; static gboolean opt_daemonize;
static gboolean opt_autoexit; static gboolean opt_autoexit;
static gboolean opt_force_ranges; 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 gint opt_port = 0;
static guint emitted_random_500s_count = 0;
typedef struct { typedef struct {
GFile *root; GFile *root;
gboolean running; 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", '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" }, { "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 }, { "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" }, { "log-file", 0, 0, G_OPTION_ARG_FILENAME, &opt_log, "Put logs here", "PATH" },
{ NULL } { NULL }
}; };
@ -187,6 +195,15 @@ do_get (OtTrivialHttpd *self,
goto out; 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] == '/') if (path[0] == '/')
path++; path++;
@ -388,6 +405,13 @@ ostree_builtin_trivial_httpd (int argc, char **argv, GCancellable *cancellable,
app->root = g_file_new_for_path (dirpath); 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) if (opt_log)
{ {
GOutputStream *stream = NULL; 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); csum_bytes = ostree_checksum_bytes_peek_validate (csum_v, &csum_error);
if (csum_error == NULL) if (csum_error == NULL)
{ {
char csum[65]; char csum[OSTREE_SHA256_STRING_LEN+1];
ostree_checksum_inplace_from_bytes (csum_bytes, csum); ostree_checksum_inplace_from_bytes (csum_bytes, csum);
g_print (" %s\n", csum); g_print (" %s\n", csum);

View File

@ -261,8 +261,11 @@ can_write (const char *path)
else else
return -errno; return -errno;
} }
if (!devino_set_contains (stbuf.st_dev, stbuf.st_ino)) if (!S_ISDIR (stbuf.st_mode))
return -EROFS; {
if (!devino_set_contains (stbuf.st_dev, stbuf.st_ino))
return -EROFS;
}
return 0; 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)) if (!ot_test_run_libtest ("setup_os_repository \"archive-z2\" \"syslinux\"", error))
goto out; goto out;
/* Make sure deployments are mutable */
g_setenv ("OSTREE_SYSROOT_DEBUG", "mutable-deployments", TRUE);
ret_sysroot = ostree_sysroot_new (sysroot_path); ret_sysroot = ostree_sysroot_new (sysroot_path);
ret = TRUE; ret = TRUE;

View File

@ -138,6 +138,7 @@ assert_file_has_content () {
if ! grep -q -e "$2" "$1"; then if ! grep -q -e "$2" "$1"; then
sed -e 's/^/# /' < "$1" >&2 sed -e 's/^/# /' < "$1" >&2
echo 1>&2 "File '$1' doesn't match regexp '$2'" echo 1>&2 "File '$1' doesn't match regexp '$2'"
cat $1
exit 1 exit 1
fi 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" echo "ok deploy with --karg, but same config"
${CMD_PREFIX} ostree admin deploy --karg-proc-cmdline --os=testos testos:testos/buildmaster/x86_64-runtime ${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 for arg in $(cat /proc/cmdline); do
# argument. I think it's unlikely that anyone doesn't have one, but assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf "options.*$arg"
# if this is not true for you, please file a bug! done
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*root=.'
echo "ok deploy --karg-proc-cmdline" 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" echo "ok instutil set-kargs --append"
${CMD_PREFIX} ostree admin instutil set-kargs --import-proc-cmdline ${CMD_PREFIX} ostree admin instutil set-kargs --import-proc-cmdline
# Here we're asserting that the *host* system has a root= kernel for arg in $(cat /proc/cmdline); do
# argument. I think it's unlikely that anyone doesn't have one, but assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf "options.*$arg"
# if this is not true for you, please file a bug! done
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*root=.'
echo "ok instutil set-kargs --import-proc-cmdline" echo "ok instutil set-kargs --import-proc-cmdline"

View File

@ -31,30 +31,30 @@ mkdir test
echo hello > test/a 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" echo "ok commit 1"
${CMD_PREFIX} $OSTREE summary --update $OSTREE summary --update
OLD_MD5=$(md5sum repo/summary) OLD_MD5=$(md5sum repo/summary)
echo hello2 > test/a 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" echo "ok commit 2"
assert_streq "$OLD_MD5" "$(md5sum repo/summary)" 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 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" echo "ok commit 3"
assert_not_streq "$OLD_MD5" "$(md5sum repo/summary)" assert_not_streq "$OLD_MD5" "$(md5sum repo/summary)"
# Check that summary --update deletes the .sig file # Check that summary --update deletes the .sig file
touch repo/summary.sig touch repo/summary.sig
${CMD_PREFIX} $OSTREE summary --update $OSTREE summary --update
assert_not_has_file repo/summary.sig 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) 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 --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 static-delta list | grep ${origrev} || exit 1
${CMD_PREFIX} ostree --repo=repo prune ${CMD_PREFIX} ostree --repo=repo prune
${CMD_PREFIX} ostree --repo=repo static-delta list | grep ${origrev} || exit 1 ${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) 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 '.') deltaprefix=$(get_assert_one_direntry_matching repo/deltas '.')
deltadir=$(get_assert_one_direntry_matching repo/deltas/${deltaprefix} '-') 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; OstreeRepoCommitModifier *modifier = NULL;
gboolean met_etc_file = FALSE; gboolean met_etc_file = FALSE;
if (skip_if_no_xattr (td))
goto out;
modifier = ostree_repo_commit_modifier_new (0, NULL, NULL, NULL); modifier = ostree_repo_commit_modifier_new (0, NULL, NULL, NULL);
ostree_repo_commit_modifier_set_xattr_callback (modifier, path_cb, ostree_repo_commit_modifier_set_xattr_callback (modifier, path_cb,
NULL, &met_etc_file); 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" setup_fake_remote_repo1 "archive-z2"
echo '1..1' echo '1..2'
repopath=${test_tmpdir}/ostree-srv/gnomerepo repopath=${test_tmpdir}/ostree-srv/gnomerepo
cp -a ${repopath} ${repopath}.orig cp -a ${repopath} ${repopath}.orig
for remoteurl in $(cat httpd-address)/ostree/gnomerepo \
file://$(pwd)/ostree-srv/gnomerepo; do
cd ${test_tmpdir} cd ${test_tmpdir}
rm repo -rf rm repo -rf
mkdir repo mkdir repo
${CMD_PREFIX} ostree --repo=repo init ${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 ${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 ${CMD_PREFIX} ostree --repo=repo pull origin main
assert_not_has_file repo/state/${rev}.commitpartial assert_not_has_file repo/state/${rev}.commitpartial
${CMD_PREFIX} ostree --repo=repo fsck ${CMD_PREFIX} ostree --repo=repo fsck
echo "ok" echo "ok"
done

View File

@ -92,8 +92,28 @@ fi
${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create1 ${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create1
assert_file_has_content refscount.create1 "^5$" 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 ${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create2
assert_file_has_content refscount.create2 "^6$" 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" echo "ok refs"

View File

@ -26,7 +26,7 @@ skip_without_user_xattrs
setup_test_repository "bare-user" setup_test_repository "bare-user"
echo "1..5" echo "1..6"
mkdir mnt 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 ${CMD_PREFIX} ostree --repo=repo commit -b test2 -s fromfuse --link-checkout-speedup --tree=dir=checkout-test2
echo "ok commit" 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"