New upstream version 2018.9.1

This commit is contained in:
Simon McVittie 2018-10-30 10:59:22 +00:00
commit 854d02fbe3
49 changed files with 973 additions and 356 deletions

View File

@ -39,7 +39,10 @@ endif
if BUILDOPT_SYSTEMD
systemdsystemunit_DATA = src/boot/ostree-prepare-root.service \
src/boot/ostree-remount.service src/boot/ostree-finalize-staged.service
src/boot/ostree-remount.service \
src/boot/ostree-finalize-staged.service \
src/boot/ostree-finalize-staged.path \
$(NULL)
systemdtmpfilesdir = $(prefix)/lib/tmpfiles.d
dist_systemdtmpfiles_DATA = src/boot/ostree-tmpfiles.conf
@ -64,6 +67,7 @@ EXTRA_DIST += src/boot/dracut/module-setup.sh \
src/boot/dracut/ostree.conf \
src/boot/mkinitcpio/ostree \
src/boot/ostree-prepare-root.service \
src/boot/ostree-finalize-staged.path \
src/boot/ostree-remount.service \
src/boot/ostree-finalize-staged.service \
src/boot/grub2/grub2-15_ostree \

View File

@ -2075,6 +2075,7 @@ EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) autogen.sh \
src/boot/dracut/module-setup.sh src/boot/dracut/ostree.conf \
src/boot/mkinitcpio/ostree \
src/boot/ostree-prepare-root.service \
src/boot/ostree-finalize-staged.path \
src/boot/ostree-remount.service \
src/boot/ostree-finalize-staged.service \
src/boot/grub2/grub2-15_ostree \
@ -2764,7 +2765,10 @@ tests_test_gpg_verify_result_LDADD = $(TESTS_LDADD) $(OT_INTERNAL_GPGME_LIBS)
@BUILDOPT_MKINITCPIO_TRUE@mkinitcpioconfdir = $(sysconfdir)
@BUILDOPT_MKINITCPIO_TRUE@mkinitcpioconf_DATA = src/boot/mkinitcpio/ostree-mkinitcpio.conf
@BUILDOPT_SYSTEMD_TRUE@systemdsystemunit_DATA = src/boot/ostree-prepare-root.service \
@BUILDOPT_SYSTEMD_TRUE@ src/boot/ostree-remount.service src/boot/ostree-finalize-staged.service
@BUILDOPT_SYSTEMD_TRUE@ src/boot/ostree-remount.service \
@BUILDOPT_SYSTEMD_TRUE@ src/boot/ostree-finalize-staged.service \
@BUILDOPT_SYSTEMD_TRUE@ src/boot/ostree-finalize-staged.path \
@BUILDOPT_SYSTEMD_TRUE@ $(NULL)
@BUILDOPT_SYSTEMD_TRUE@systemdtmpfilesdir = $(prefix)/lib/tmpfiles.d
@BUILDOPT_SYSTEMD_TRUE@dist_systemdtmpfiles_DATA = src/boot/ostree-tmpfiles.conf

View File

@ -74,6 +74,22 @@ The [BuildStream](https://gitlab.com/BuildStream/buildstream) build and
integration tool uses libostree as a caching system to store and share
built artifacts.
Language bindings
----
libostree is accessible via [GObject Introspection](https://gi.readthedocs.io/en/latest/);
any language which has implemented the GI binding model should work.
For example, Both [pygobject](https://pygobject.readthedocs.io/en/latest/)
and [gjs](https://gitlab.gnome.org/GNOME/gjs) are known to work
and further are actually used in libostree's test suite today.
Some bindings take the approach of using GI as a lower level and
write higher level manual bindings on top; this is more common
for statically compiled languages. Here's a list of such bindings:
- [ostree-go](https://github.com/ostreedev/ostree-go/)
- [rust-libostree](https://gitlab.com/fkrull/rust-libostree/)
Building
--------

View File

@ -2420,17 +2420,17 @@ ostree_check_version (<em class="parameter"><code><span class="type">guint</span
<a name="OSTREE-MAX-METADATA-SIZE:CAPS"></a><h3>OSTREE_MAX_METADATA_SIZE</h3>
<pre class="programlisting">#define OSTREE_MAX_METADATA_SIZE (10 * 1024 * 1024)
</pre>
<p>Maximum permitted size in bytes of metadata objects. This is an
arbitrary number, but really, no one should be putting humongous
data in metadata.</p>
<p>Default limit for maximum permitted size in bytes of metadata objects fetched
over HTTP (including repo/config files, refs, and commit/dirtree/dirmeta
objects). This is an arbitrary number intended to mitigate disk space
exhaustion attacks.</p>
</div>
<hr>
<div class="refsect2">
<a name="OSTREE-MAX-METADATA-WARN-SIZE:CAPS"></a><h3>OSTREE_MAX_METADATA_WARN_SIZE</h3>
<pre class="programlisting">#define OSTREE_MAX_METADATA_WARN_SIZE (7 * 1024 * 1024)
</pre>
<p>Objects committed above this size will be allowed, but a warning
will be emitted.</p>
<p>This variable is no longer meaningful, it is kept only for compatibility.</p>
</div>
<hr>
<div class="refsect2">

View File

@ -106,6 +106,14 @@
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-remove" title="ostree_mutable_tree_remove ()">ostree_mutable_tree_remove</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-ensure-dir" title="ostree_mutable_tree_ensure_dir ()">ostree_mutable_tree_ensure_dir</a> <span class="c_punctuation">()</span>
</td>
</tr>
@ -307,6 +315,52 @@ ostree_mutable_tree_replace_file (<em class="parameter"><code><a class="link" hr
</div>
<hr>
<div class="refsect2">
<a name="ostree-mutable-tree-remove"></a><h3>ostree_mutable_tree_remove ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_mutable_tree_remove (<em class="parameter"><code><a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html#OstreeMutableTree" title="OstreeMutableTree"><span class="type">OstreeMutableTree</span></a> *self</code></em>,
<em class="parameter"><code>const <span class="type">char</span> *name</code></em>,
<em class="parameter"><code><span class="type">gboolean</span> allow_noent</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>Remove the file or subdirectory named <em class="parameter"><code>name</code></em>
from the mutable tree <em class="parameter"><code>self</code></em>
.</p>
<div class="refsect3">
<a name="ostree-mutable-tree-remove.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>Tree</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>name</p></td>
<td class="parameter_description"><p>Name of file or subdirectory to remove</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>allow_noent</p></td>
<td class="parameter_description"><p>If <em class="parameter"><code>FALSE</code></em>
, an error will be thrown if <em class="parameter"><code>name</code></em>
does not exist in the tree</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>a <span class="type">GError</span></p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
</div>
<hr>
<div class="refsect2">
<a name="ostree-mutable-tree-ensure-dir"></a><h3>ostree_mutable_tree_ensure_dir ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_mutable_tree_ensure_dir (<em class="parameter"><code><a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html#OstreeMutableTree" title="OstreeMutableTree"><span class="type">OstreeMutableTree</span></a> *self</code></em>,

View File

@ -153,6 +153,14 @@
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-OstreeRepo.html#ostree-repo-get-min-free-space-bytes" title="ostree_repo_get_min_free_space_bytes ()">ostree_repo_get_min_free_space_bytes</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">GKeyFile</span> *
</td>
<td class="function_name">
@ -168,6 +176,13 @@
</td>
</tr>
<tr>
<td class="function_type">const <span class="returnvalue">gchar</span> * const *
</td>
<td class="function_name">
<a class="link" href="ostree-OstreeRepo.html#ostree-repo-get-default-repo-finders" title="ostree_repo_get_default_repo_finders ()">ostree_repo_get_default_repo_finders</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">guint</span>
</td>
@ -1209,16 +1224,18 @@
<a name="ostree-OstreeRepo.description"></a><h2>Description</h2>
<p>The <a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> is like git, a content-addressed object store.
Unlike git, it records uid, gid, and extended attributes.</p>
<p>There are three possible "modes" for an <a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a>;
<a class="link" href="ostree-OstreeRepo.html#OSTREE-REPO-MODE-BARE:CAPS"><code class="literal">OSTREE_REPO_MODE_BARE</code></a> is very simple - content files are
represented exactly as they are, and checkouts are just hardlinks.
<a class="link" href="ostree-OstreeRepo.html#OSTREE-REPO-MODE-BARE-USER:CAPS"><code class="literal">OSTREE_REPO_MODE_BARE_USER</code></a> is similar, except the uid/gids are not
set on the files, and checkouts as hardlinks hardlinks work only for user checkouts.
A <a class="link" href="ostree-OstreeRepo.html#OSTREE-REPO-MODE-ARCHIVE-Z2:CAPS"><code class="literal">OSTREE_REPO_MODE_ARCHIVE_Z2</code></a> repository in contrast stores
<p>There are four possible "modes" for an <a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a>; <a class="link" href="ostree-OstreeRepo.html#OSTREE-REPO-MODE-BARE:CAPS"><code class="literal">OSTREE_REPO_MODE_BARE</code></a>
is very simple - content files are represented exactly as they are, and
checkouts are just hardlinks. <a class="link" href="ostree-OstreeRepo.html#OSTREE-REPO-MODE-BARE-USER:CAPS"><code class="literal">OSTREE_REPO_MODE_BARE_USER</code></a> is similar, except
the uid/gids are not set on the files, and checkouts as hardlinks work only
for user checkouts. <a class="link" href="ostree-OstreeRepo.html#OSTREE-REPO-MODE-BARE-USER-ONLY:CAPS"><code class="literal">OSTREE_REPO_MODE_BARE_USER_ONLY</code></a> is the same as
BARE_USER, but all metadata is not stored, so it can only be used for user
checkouts. This mode does not require xattrs. A <a class="link" href="ostree-OstreeRepo.html#OSTREE-REPO-MODE-ARCHIVE:CAPS"><code class="literal">OSTREE_REPO_MODE_ARCHIVE</code></a>
(also known as <a class="link" href="ostree-OstreeRepo.html#OSTREE-REPO-MODE-ARCHIVE-Z2:CAPS"><code class="literal">OSTREE_REPO_MODE_ARCHIVE_Z2</code></a>) repository in contrast stores
content files zlib-compressed. It is suitable for non-root-owned
repositories that can be served via a static HTTP server.</p>
<p>Creating an <a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> does not invoke any file I/O, and thus needs
to be initialized, either from an existing contents or with a new
to be initialized, either from existing contents or as a new
repository. If you have an existing repo, use <a class="link" href="ostree-OstreeRepo.html#ostree-repo-open" title="ostree_repo_open ()"><code class="function">ostree_repo_open()</code></a>
to load it from disk and check its validity. To initialize a new
repository in the given filepath, use <a class="link" href="ostree-OstreeRepo.html#ostree-repo-create" title="ostree_repo_create ()"><code class="function">ostree_repo_create()</code></a> instead.</p>
@ -1664,6 +1681,14 @@ ostree_repo_get_mode (<em class="parameter"><code><a class="link" href="ostree-O
</div>
<hr>
<div class="refsect2">
<a name="ostree-repo-get-min-free-space-bytes"></a><h3>ostree_repo_get_min_free_space_bytes ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_repo_get_min_free_space_bytes (<em class="parameter"><code><a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> *self</code></em>,
<em class="parameter"><code><span class="type">guint64</span> *out_reserved_bytes</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
</div>
<hr>
<div class="refsect2">
<a name="ostree-repo-get-config"></a><h3>ostree_repo_get_config ()</h3>
<pre class="programlisting"><span class="returnvalue">GKeyFile</span> *
ostree_repo_get_config (<em class="parameter"><code><a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> *self</code></em>);</pre>
@ -1705,6 +1730,35 @@ repository (to see whether a ref was written).</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-repo-get-default-repo-finders"></a><h3>ostree_repo_get_default_repo_finders ()</h3>
<pre class="programlisting">const <span class="returnvalue">gchar</span> * const *
ostree_repo_get_default_repo_finders (<em class="parameter"><code><a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> *self</code></em>);</pre>
<p>Get the set of default repo finders configured. See the documentation for
the "core.default-repo-finders" config key.</p>
<div class="refsect3">
<a name="ostree-repo-get-default-repo-finders.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody><tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>an <a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a></p></td>
<td class="parameter_annotations"> </td>
</tr></tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-repo-get-default-repo-finders.returns"></a><h4>Returns</h4>
<p><code class="literal">NULL</code>-terminated array of strings. </p>
<p><span class="annotation">[<a href="http://foldoc.org/array"><span class="acronym">array</span></a> zero-terminated=1][<a href="http://foldoc.org/element-type"><span class="acronym">element-type</span></a> utf8]</span></p>
</div>
<p class="since">Since: 2018.9</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-repo-hash"></a><h3>ostree_repo_hash ()</h3>
<pre class="programlisting"><span class="returnvalue">guint</span>
ostree_repo_hash (<em class="parameter"><code><a class="link" href="ostree-OstreeRepo.html#OstreeRepo" title="OstreeRepo"><span class="type">OstreeRepo</span></a> *self</code></em>);</pre>
@ -7111,6 +7165,7 @@ string to pull the latest commit for that ref</p></li>
<li class="listitem"><p>require-static-deltas (b): Require static deltas</p></li>
<li class="listitem"><p>override-commit-ids (as): Array of specific commit IDs to fetch for refs</p></li>
<li class="listitem"><p>timestamp-check (b): Verify commit timestamps are newer than current (when pulling via ref); Since: 2017.11</p></li>
<li class="listitem"><p>metadata-size-restriction (t): Restrict metadata objects to a maximum number of bytes; 0 to disable. Since: 2018.9</p></li>
<li class="listitem"><p>dry-run (b): Only print information on what will be downloaded (requires static deltas)</p></li>
<li class="listitem"><p>override-url (s): Fetch objects from this URL if remote specifies no metalink in options</p></li>
<li class="listitem"><p>inherit-transaction (b): Don't initiate, finish or abort a transaction, useful to do multiple pulls in one transaction.</p></li>
@ -8127,7 +8182,8 @@ by <a class="link" href="ostree-OstreeRepo.html#ostree-repo-load-commit" title="
gboolean no_copy_fallback;
gboolean force_copy; /* Since: 2017.6 */
gboolean bareuseronly_dirs; /* Since: 2017.7 */
gboolean unused_bools[5];
gboolean force_copy_zerosized; /* Since: 2018.9 */
gboolean unused_bools[4];
/* 4 byte hole on 64 bit */
const char *subpath;

View File

@ -98,8 +98,10 @@
<keyword type="function" name="ostree_repo_create ()" link="ostree-OstreeRepo.html#ostree-repo-create"/>
<keyword type="function" name="ostree_repo_get_path ()" link="ostree-OstreeRepo.html#ostree-repo-get-path"/>
<keyword type="function" name="ostree_repo_get_mode ()" link="ostree-OstreeRepo.html#ostree-repo-get-mode"/>
<keyword type="function" name="ostree_repo_get_min_free_space_bytes ()" link="ostree-OstreeRepo.html#ostree-repo-get-min-free-space-bytes"/>
<keyword type="function" name="ostree_repo_get_config ()" link="ostree-OstreeRepo.html#ostree-repo-get-config"/>
<keyword type="function" name="ostree_repo_get_dfd ()" link="ostree-OstreeRepo.html#ostree-repo-get-dfd"/>
<keyword type="function" name="ostree_repo_get_default_repo_finders ()" link="ostree-OstreeRepo.html#ostree-repo-get-default-repo-finders" since="2018.9"/>
<keyword type="function" name="ostree_repo_hash ()" link="ostree-OstreeRepo.html#ostree-repo-hash" since="2017.12"/>
<keyword type="function" name="ostree_repo_equal ()" link="ostree-OstreeRepo.html#ostree-repo-equal" since="2017.12"/>
<keyword type="function" name="ostree_repo_copy_config ()" link="ostree-OstreeRepo.html#ostree-repo-copy-config"/>
@ -246,6 +248,7 @@
<keyword type="function" name="ostree_mutable_tree_set_contents_checksum ()" link="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-set-contents-checksum"/>
<keyword type="function" name="ostree_mutable_tree_get_contents_checksum ()" link="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-get-contents-checksum"/>
<keyword type="function" name="ostree_mutable_tree_replace_file ()" link="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-replace-file"/>
<keyword type="function" name="ostree_mutable_tree_remove ()" link="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-remove"/>
<keyword type="function" name="ostree_mutable_tree_ensure_dir ()" link="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-ensure-dir"/>
<keyword type="function" name="ostree_mutable_tree_lookup ()" link="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-lookup"/>
<keyword type="function" name="ostree_mutable_tree_ensure_parent_dirs ()" link="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-ensure-parent-dirs"/>

View File

@ -539,6 +539,10 @@ ostree_collection_ref_new, function in ostree-ref
</dt>
<dd></dd>
<dt>
OSTREE_META_KEY_DEPLOY_COLLECTION_ID, macro in ostree-repo-experimental
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html#OstreeMutableTree" title="OstreeMutableTree">OstreeMutableTree</a>, typedef in <a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html" title="In-memory modifiable filesystem tree">In-memory modifiable filesystem tree</a>
</dt>
<dd></dd>
@ -587,6 +591,10 @@ ostree_collection_ref_new, function in ostree-ref
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-remove" title="ostree_mutable_tree_remove ()">ostree_mutable_tree_remove</a>, function in <a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html" title="In-memory modifiable filesystem tree">In-memory modifiable filesystem tree</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html#ostree-mutable-tree-replace-file" title="ostree_mutable_tree_replace_file ()">ostree_mutable_tree_replace_file</a>, function in <a class="link" href="ostree-In-memory-modifiable-filesystem-tree.html" title="In-memory modifiable filesystem tree">In-memory modifiable filesystem tree</a>
</dt>
<dd></dd>
@ -1022,6 +1030,10 @@ ostree_repo_get_collection_id, function in ostree-misc-experimental
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-OstreeRepo.html#ostree-repo-get-default-repo-finders" title="ostree_repo_get_default_repo_finders ()">ostree_repo_get_default_repo_finders</a>, function in <a class="link" href="ostree-OstreeRepo.html" title="OstreeRepo: Content-addressed object store">OstreeRepo</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-OstreeRepo.html#ostree-repo-get-dfd" title="ostree_repo_get_dfd ()">ostree_repo_get_dfd</a>, function in <a class="link" href="ostree-OstreeRepo.html" title="OstreeRepo: Content-addressed object store">OstreeRepo</a>
</dt>
<dd></dd>
@ -1030,6 +1042,10 @@ ostree_repo_get_collection_id, function in ostree-misc-experimental
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-OstreeRepo.html#ostree-repo-get-min-free-space-bytes" title="ostree_repo_get_min_free_space_bytes ()">ostree_repo_get_min_free_space_bytes</a>, function in <a class="link" href="ostree-OstreeRepo.html" title="OstreeRepo: Content-addressed object store">OstreeRepo</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-OstreeRepo.html#ostree-repo-get-mode" title="ostree_repo_get_mode ()">ostree_repo_get_mode</a>, function in <a class="link" href="ostree-OstreeRepo.html" title="OstreeRepo: Content-addressed object store">OstreeRepo</a>
</dt>
<dd></dd>

View File

@ -257,6 +257,7 @@ ostree_mutable_tree_get_metadata_checksum
ostree_mutable_tree_set_contents_checksum
ostree_mutable_tree_get_contents_checksum
ostree_mutable_tree_replace_file
ostree_mutable_tree_remove
ostree_mutable_tree_ensure_dir
ostree_mutable_tree_lookup
ostree_mutable_tree_ensure_parent_dirs
@ -294,8 +295,10 @@ ostree_repo_create_at
ostree_repo_create
ostree_repo_get_path
ostree_repo_get_mode
ostree_repo_get_min_free_space_bytes
ostree_repo_get_config
ostree_repo_get_dfd
ostree_repo_get_default_repo_finders
ostree_repo_hash
ostree_repo_equal
ostree_repo_copy_config
@ -596,6 +599,7 @@ ostree_repo_pull_from_remotes_async
ostree_repo_pull_from_remotes_finish
ostree_repo_resolve_keyring_for_collection
OSTREE_REPO_METADATA_REF
OSTREE_META_KEY_DEPLOY_COLLECTION_ID
</SECTION>
<SECTION>

View File

@ -24,12 +24,6 @@
# - Structured option arguments (e.g. --foo KEY=VALUE) are not parsed.
#
# - Static deltas could likely be completed. (e.g. ostree static-delta delete [TAB])
#
# - The "--repo PATH" option needs to come after the subcommand or it
# won't be picked up for completion of subsequent options.
# i.e. ostree commit --repo PATH ... <-- works
# ostree --repo PATH commit ... <-- does not work
# (Possibly an easy fix.)
# Finds the position of the first non-flag word.
@ -183,9 +177,16 @@ __ostree_subcommands() {
# This handles "ostree [TAB]" (without a subcommand).
_ostree_ostree() {
case "$prev" in
--repo)
__ostree_compreply_dirs_only
return 0
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "$main_boolean_options" -- "$cur" ) )
COMPREPLY=( $( compgen -W "$main_options" -- "$cur" ) )
;;
*)
COMPREPLY=( $( compgen -W "$commands" -- "$cur" ) )
@ -1753,6 +1754,14 @@ _ostree() {
--verbose -v
--version
"
local main_options_with_args="
--repo
"
local main_options_with_args_glob=$( __ostree_to_extglob "$main_options_with_args" )
local main_options="
$main_boolean_options
$main_options_with_args
"
COMPREPLY=()
local cur prev words cword

24
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for libostree 2018.8.
# Generated by GNU Autoconf 2.69 for libostree 2018.9.
#
# Report bugs to <walters@verbum.org>.
#
@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libostree'
PACKAGE_TARNAME='libostree'
PACKAGE_VERSION='2018.8'
PACKAGE_STRING='libostree 2018.8'
PACKAGE_VERSION='2018.9'
PACKAGE_STRING='libostree 2018.9'
PACKAGE_BUGREPORT='walters@verbum.org'
PACKAGE_URL=''
@ -1547,7 +1547,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libostree 2018.8 to adapt to many kinds of systems.
\`configure' configures libostree 2018.9 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1617,7 +1617,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libostree 2018.8:";;
short | recursive ) echo "Configuration of libostree 2018.9:";;
esac
cat <<\_ACEOF
@ -1864,7 +1864,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libostree configure 2018.8
libostree configure 2018.9
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -2336,7 +2336,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libostree $as_me 2018.8, which was
It was created by libostree $as_me 2018.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -3204,7 +3204,7 @@ fi
# Define the identity of the package.
PACKAGE='libostree'
VERSION='2018.8'
VERSION='2018.9'
# Some tools Automake needs.
@ -5938,9 +5938,9 @@ test -n "$YACC" || YACC="yacc"
YEAR_VERSION=2018
RELEASE_VERSION=8
RELEASE_VERSION=9
PACKAGE_VERSION=2018.8
PACKAGE_VERSION=2018.9
if echo "$CFLAGS" | grep -q -E -e '-Werror($| )'; then :
@ -18623,7 +18623,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libostree $as_me 2018.8, which was
This file was extended by libostree $as_me 2018.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -18689,7 +18689,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libostree config.status 2018.8
libostree config.status 2018.9
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -4,7 +4,7 @@ dnl update libostree-released.sym from libostree-devel.sym, and update the check
dnl in test-symbols.sh, and also set is_release_build=yes below. Then make
dnl another post-release commit to bump the version, and set is_release_build=no.
m4_define([year_version], [2018])
m4_define([release_version], [8])
m4_define([release_version], [9])
m4_define([package_version], [year_version.release_version])
AC_INIT([libostree], [package_version], [walters@verbum.org])
is_release_build=yes

View File

@ -83,11 +83,6 @@ Boston, MA 02111-1307, USA.
USB mounts use signed per-repo and per-commit metadata instead of
summary signatures.
</para>
<para>
This command relies on the summary file in the source repo, so you
may want to run <command>ostree summary -u</command> before running
this command.
</para>
</refsect1>
<refsect1>
@ -112,6 +107,15 @@ Boston, MA 02111-1307, USA.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--commit</option>=COMMIT</term>
<listitem><para>
Pull COMMIT instead of whatever REF points to. This can only
be used if a single ref is specified.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -198,6 +198,38 @@ Boston, MA 02111-1307, USA.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>locking</varname></term>
<listitem><para>Boolean value controlling whether or not OSTree does
repository locking internally. This uses file locks and is
hence for multiple process exclusion (e.g. Flatpak and OSTree
writing to the same repository separately). This is enabled by
default since 2018.5.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>lock-timeout-secs</varname></term>
<listitem><para>Integer value controlling the number of seconds to
block while attempting to acquire a lock (see above). A value
of -1 means block indefinitely. The default value is 30.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>default-repo-finders</varname></term>
<listitem><para>Semicolon separated default list of finders (sources
for refs) to use when pulling. This can be used to disable
pulling from mounted filesystems, peers on the local network,
or the Internet. However note that it only applies when a set
of finders isn't explicitly specified, either by a consumer of
libostree API or on the command line. Possible values:
<literal>config</literal>, <literal>lan</literal>, and
<literal>mount</literal> (or any combination thereof). If unset, this
defaults to <literal>config;mount;</literal> (since the LAN finder is
costly).
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -36,7 +36,7 @@ depends() {
install() {
dracut_install /usr/lib/ostree/ostree-prepare-root
inst_simple "${systemdsystemunitdir}/ostree-prepare-root.service"
mkdir -p "${initdir}${systemdsystemconfdir}/initrd-switch-root.target.wants"
mkdir -p "${initdir}${systemdsystemconfdir}/initrd-root-fs.target.wants"
ln_r "${systemdsystemunitdir}/ostree-prepare-root.service" \
"${systemdsystemconfdir}/initrd-switch-root.target.wants/ostree-prepare-root.service"
"${systemdsystemconfdir}/initrd-root-fs.target.wants/ostree-prepare-root.service"
}

View File

@ -0,0 +1,28 @@
# Copyright (C) 2018 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# For some implementation discussion, see:
# https://lists.freedesktop.org/archives/systemd-devel/2018-March/040557.html
[Unit]
Description=OSTree Monitor Staged Deployment
Documentation=man:ostree(1)
[Path]
PathExists=/run/ostree/staged-deployment
[Install]
WantedBy=multi-user.target

View File

@ -19,6 +19,7 @@
# https://lists.freedesktop.org/archives/systemd-devel/2018-March/040557.html
[Unit]
Description=OSTree Finalize Staged Deployment
Documentation=man:ostree(1)
ConditionPathExists=/run/ostree-booted
DefaultDependencies=no
@ -31,6 +32,7 @@ Conflicts=final.target
Type=oneshot
RemainAfterExit=yes
ExecStop=/usr/bin/ostree admin finalize-staged
[Install]
WantedBy=multi-user.target
# This is a quite long timeout intentionally; the failure mode
# here is that people don't get an upgrade. We need to handle
# cases with slow rotational media, etc.
TimeoutStopSec=5m

View File

@ -17,13 +17,13 @@
[Unit]
Description=OSTree Prepare OS/
Documentation=man:ostree(1)
DefaultDependencies=no
ConditionKernelCommandLine=ostree
ConditionPathExists=/etc/initrd-release
OnFailure=emergency.target
After=initrd-switch-root.target
Before=initrd-switch-root.service
Before=plymouth-switch-root.service
After=sysroot.mount
Before=initrd-root-fs.target
[Service]
Type=oneshot
@ -31,3 +31,4 @@ ExecStart=/usr/lib/ostree/ostree-prepare-root /sysroot
StandardInput=null
StandardOutput=syslog
StandardError=syslog+console
RemainAfterExit=yes

View File

@ -16,7 +16,8 @@
# Boston, MA 02111-1307, USA.
[Unit]
Description=OSTree Remount OS/ bind mounts
Description=OSTree Remount OS/ Bind Mounts
Documentation=man:ostree(1)
DefaultDependencies=no
ConditionKernelCommandLine=ostree
OnFailure=emergency.target

View File

@ -18,8 +18,6 @@
***/
/* Add new symbols here. Release commits should copy this section into -released.sym. */
LIBOSTREE_2018.9 {
} LIBOSTREE_2018.7;
/* Stub section for the stable release *after* this development one; don't
* edit this other than to update the last number. This is just a copy/paste

View File

@ -536,6 +536,12 @@ global:
/* No new symbols in 2018.8 */
LIBOSTREE_2018.9 {
ostree_mutable_tree_remove;
ostree_repo_get_min_free_space_bytes;
ostree_repo_get_default_repo_finders;
} LIBOSTREE_2018.7;
/* NOTE: Only add more content here in release commits! See the
* comments at the top of this file.
*/

View File

@ -228,7 +228,7 @@ idle_invoke_async_progress (gpointer user_data)
OstreeAsyncProgress *self = user_data;
g_mutex_lock (&self->lock);
self->idle_source = NULL;
g_clear_pointer (&self->idle_source, g_source_unref);
g_mutex_unlock (&self->lock);
g_signal_emit (self, signals[CHANGED], 0);

View File

@ -57,7 +57,8 @@ struct _OstreeBootloaderGrub2
GObject parent_instance;
OstreeSysroot *sysroot;
GFile *config_path_bios;
GFile *config_path_bios_1;
GFile *config_path_bios_2;
GFile *config_path_efi;
gboolean is_efi;
};
@ -77,7 +78,8 @@ _ostree_bootloader_grub2_query (OstreeBootloader *bootloader,
OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
/* Look for the BIOS path first */
if (g_file_query_exists (self->config_path_bios, NULL))
if (g_file_query_exists (self->config_path_bios_1, NULL) ||
g_file_query_exists (self->config_path_bios_2, NULL))
{
/* If we found it, we're done */
*out_is_active = TRUE;
@ -460,7 +462,8 @@ _ostree_bootloader_grub2_finalize (GObject *object)
OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (object);
g_clear_object (&self->sysroot);
g_clear_object (&self->config_path_bios);
g_clear_object (&self->config_path_bios_1);
g_clear_object (&self->config_path_bios_2);
g_clear_object (&self->config_path_efi);
G_OBJECT_CLASS (_ostree_bootloader_grub2_parent_class)->finalize (object);
@ -493,6 +496,9 @@ _ostree_bootloader_grub2_new (OstreeSysroot *sysroot)
{
OstreeBootloaderGrub2 *self = g_object_new (OSTREE_TYPE_BOOTLOADER_GRUB2, NULL);
self->sysroot = g_object_ref (sysroot);
self->config_path_bios = g_file_resolve_relative_path (self->sysroot->path, "boot/grub2/grub.cfg");
/* Used by (at least) Debian */
self->config_path_bios_1 = g_file_resolve_relative_path (self->sysroot->path, "boot/grub/grub.cfg");
/* Used by (at least) Fedora */
self->config_path_bios_2 = g_file_resolve_relative_path (self->sysroot->path, "boot/grub2/grub.cfg");
return self;
}

View File

@ -32,17 +32,17 @@ G_BEGIN_DECLS
/**
* OSTREE_MAX_METADATA_SIZE:
*
* Maximum permitted size in bytes of metadata objects. This is an
* arbitrary number, but really, no one should be putting humongous
* data in metadata.
* Default limit for maximum permitted size in bytes of metadata objects fetched
* over HTTP (including repo/config files, refs, and commit/dirtree/dirmeta
* objects). This is an arbitrary number intended to mitigate disk space
* exhaustion attacks.
*/
#define OSTREE_MAX_METADATA_SIZE (10 * 1024 * 1024)
/**
* OSTREE_MAX_METADATA_WARN_SIZE:
*
* Objects committed above this size will be allowed, but a warning
* will be emitted.
* This variable is no longer meaningful, it is kept only for compatibility.
*/
#define OSTREE_MAX_METADATA_WARN_SIZE (7 * 1024 * 1024)

View File

@ -172,6 +172,9 @@ _ostree_fetcher_finalize (GObject *object)
curl_multi_cleanup (self->multi);
g_free (self->remote_name);
g_free (self->tls_ca_db_path);
g_free (self->tls_client_cert_path);
g_free (self->tls_client_key_path);
g_free (self->cookie_jar_path);
g_free (self->proxy);
g_assert_cmpint (g_hash_table_size (self->outstanding_requests), ==, 0);
@ -319,15 +322,13 @@ check_multi_info (OstreeFetcher *fetcher)
{
/* Handle file not found */
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"%s",
curl_easy_strerror (curlres));
"%s", curl_easy_strerror (curlres));
}
else
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "[%u] %s",
curlres,
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
"While fetching %s: [%u] %s", eff_url, curlres,
curl_easy_strerror (curlres));
if (req->fetcher->remote_name)
_ostree_fetcher_journal_failure (req->fetcher->remote_name,
eff_url, curl_easy_strerror (curlres));
}

View File

@ -172,6 +172,7 @@ _ostree_fetcher_journal_failure (const char *remote_name,
"MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_HTTP_FAILURE_ID),
"OSTREE_REMOTE=%s", remote_name,
"OSTREE_URL=%s", url,
"PRIORITY=%i", LOG_ERR,
NULL);
#endif
}

View File

@ -305,31 +305,57 @@ ostree_mutable_tree_replace_file (OstreeMutableTree *self,
const char *checksum,
GError **error)
{
gboolean ret = FALSE;
g_return_val_if_fail (name != NULL, FALSE);
if (!ot_util_filename_validate (name, error))
goto out;
return FALSE;
if (!_ostree_mutable_tree_make_whole (self, NULL, error))
goto out;
return FALSE;
if (g_hash_table_lookup (self->subdirs, name))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Can't replace directory with file: %s", name);
goto out;
}
return glnx_throw (error, "Can't replace directory with file: %s", name);
invalidate_contents_checksum (self);
g_hash_table_replace (self->files,
g_strdup (name),
g_strdup (checksum));
return TRUE;
}
ret = TRUE;
out:
return ret;
/**
* ostree_mutable_tree_remove:
* @self: Tree
* @name: Name of file or subdirectory to remove
* @allow_noent: If @FALSE, an error will be thrown if @name does not exist in the tree
* @error: a #GError
*
* Remove the file or subdirectory named @name from the mutable tree @self.
*/
gboolean
ostree_mutable_tree_remove (OstreeMutableTree *self,
const char *name,
gboolean allow_noent,
GError **error)
{
g_return_val_if_fail (name != NULL, FALSE);
if (!ot_util_filename_validate (name, error))
return FALSE;
if (!_ostree_mutable_tree_make_whole (self, NULL, error))
return FALSE;
if (!g_hash_table_remove (self->files, name) &&
!g_hash_table_remove (self->subdirs, name))
{
if (allow_noent)
return TRUE; /* NB: early return */
return set_error_noent (error, name);
}
invalidate_contents_checksum (self);
return TRUE;
}
/**
@ -348,25 +374,19 @@ ostree_mutable_tree_ensure_dir (OstreeMutableTree *self,
OstreeMutableTree **out_subdir,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(OstreeMutableTree) ret_dir = NULL;
g_return_val_if_fail (name != NULL, FALSE);
if (!ot_util_filename_validate (name, error))
goto out;
return FALSE;
if (!_ostree_mutable_tree_make_whole (self, NULL, error))
goto out;
return FALSE;
if (g_hash_table_lookup (self->files, name))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Can't replace file with directory: %s", name);
goto out;
}
return glnx_throw (error, "Can't replace file with directory: %s", name);
ret_dir = ot_gobject_refz (g_hash_table_lookup (self->subdirs, name));
g_autoptr(OstreeMutableTree) ret_dir =
ot_gobject_refz (g_hash_table_lookup (self->subdirs, name));
if (!ret_dir)
{
ret_dir = ostree_mutable_tree_new ();
@ -374,10 +394,9 @@ ostree_mutable_tree_ensure_dir (OstreeMutableTree *self,
insert_child_mtree (self, name, g_object_ref (ret_dir));
}
ret = TRUE;
ot_transfer_out_value (out_subdir, &ret_dir);
out:
return ret;
if (out_subdir)
*out_subdir = g_steal_pointer (&ret_dir);
return TRUE;
}
gboolean
@ -387,29 +406,24 @@ ostree_mutable_tree_lookup (OstreeMutableTree *self,
OstreeMutableTree **out_subdir,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(OstreeMutableTree) ret_subdir = NULL;
g_autofree char *ret_file_checksum = NULL;
if (!_ostree_mutable_tree_make_whole (self, NULL, error))
goto out;
return FALSE;
ret_subdir = ot_gobject_refz (g_hash_table_lookup (self->subdirs, name));
g_autofree char *ret_file_checksum = NULL;
g_autoptr(OstreeMutableTree) ret_subdir =
ot_gobject_refz (g_hash_table_lookup (self->subdirs, name));
if (!ret_subdir)
{
ret_file_checksum = g_strdup (g_hash_table_lookup (self->files, name));
if (!ret_file_checksum)
{
set_error_noent (error, name);
goto out;
}
return set_error_noent (error, name);
}
ret = TRUE;
ot_transfer_out_value (out_file_checksum, &ret_file_checksum);
ot_transfer_out_value (out_subdir, &ret_subdir);
out:
return ret;
if (out_file_checksum)
*out_file_checksum = g_steal_pointer (&ret_file_checksum);
if (out_subdir)
*out_subdir = g_steal_pointer (&ret_subdir);
return TRUE;
}
/**
@ -430,30 +444,22 @@ ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree *self,
OstreeMutableTree **out_parent,
GError **error)
{
gboolean ret = FALSE;
int i;
OstreeMutableTree *subdir = self; /* nofree */
g_autoptr(OstreeMutableTree) ret_parent = NULL;
g_assert (metadata_checksum != NULL);
if (!_ostree_mutable_tree_make_whole (self, NULL, error))
goto out;
g_assert (metadata_checksum != NULL);
return FALSE;
if (!self->metadata_checksum)
ostree_mutable_tree_set_metadata_checksum (self, metadata_checksum);
for (i = 0; i+1 < split_path->len; i++)
OstreeMutableTree *subdir = self; /* nofree */
for (guint i = 0; i+1 < split_path->len; i++)
{
OstreeMutableTree *next;
const char *name = split_path->pdata[i];
if (g_hash_table_lookup (subdir->files, name))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Can't replace file with directory: %s", name);
goto out;
}
return glnx_throw (error, "Can't replace file with directory: %s", name);
next = g_hash_table_lookup (subdir->subdirs, name);
if (!next)
@ -467,12 +473,9 @@ ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree *self,
subdir = next;
}
ret_parent = g_object_ref (subdir);
ret = TRUE;
ot_transfer_out_value (out_parent, &ret_parent);
out:
return ret;
if (out_parent)
*out_parent = g_object_ref (subdir);
return TRUE;
}
const char empty_tree_csum[] = "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d";

View File

@ -77,6 +77,12 @@ gboolean ostree_mutable_tree_replace_file (OstreeMutableTree *self,
const char *checksum,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_mutable_tree_remove (OstreeMutableTree *self,
const char *name,
gboolean allow_noent,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_mutable_tree_ensure_dir (OstreeMutableTree *self,
const char *name,

View File

@ -196,6 +196,7 @@ static gboolean
create_file_copy_from_input_at (OstreeRepo *repo,
OstreeRepoCheckoutAtOptions *options,
CheckoutState *state,
const char *checksum,
GFileInfo *file_info,
GVariant *xattrs,
GInputStream *input,
@ -358,8 +359,35 @@ create_file_copy_from_input_at (OstreeRepo *repo,
replace_mode = GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST;
break;
case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL:
/* We don't support copying in union identical */
g_assert_not_reached ();
{
replace_mode = GLNX_LINK_TMPFILE_NOREPLACE;
struct stat dest_stbuf;
if (!glnx_fstatat_allow_noent (destination_dfd, destination_name, &dest_stbuf,
AT_SYMLINK_NOFOLLOW, error))
return FALSE;
if (errno == 0)
{
/* We do a checksum comparison; see also equivalent code in
* checkout_file_hardlink().
*/
OstreeChecksumFlags flags = 0;
if (repo->disable_xattrs)
flags |= OSTREE_CHECKSUM_FLAGS_IGNORE_XATTRS;
g_autofree char *actual_checksum = NULL;
if (!ostree_checksum_file_at (destination_dfd, destination_name,
&dest_stbuf, OSTREE_OBJECT_TYPE_FILE,
flags, &actual_checksum, cancellable, error))
return FALSE;
if (g_str_equal (checksum, actual_checksum))
return TRUE;
/* Otherwise, fall through and do the link, we should
* get EEXIST.
*/
}
}
break;
}
@ -586,6 +614,7 @@ checkout_one_file_at (OstreeRepo *repo,
const gboolean is_symlink = (g_file_info_get_file_type (source_info) == G_FILE_TYPE_SYMBOLIC_LINK);
const gboolean is_whiteout = (!is_symlink && options->process_whiteouts &&
g_str_has_prefix (destination_name, WHITEOUT_PREFIX));
const gboolean is_reg_zerosized = (!is_symlink && g_file_info_get_size (source_info) == 0);
/* First, see if it's a Docker whiteout,
* https://github.com/docker/docker/blob/1a714e76a2cb9008cd19609059e9988ff1660b78/pkg/archive/whiteouts.go
@ -604,6 +633,10 @@ checkout_one_file_at (OstreeRepo *repo,
need_copy = FALSE;
}
else if (options->force_copy_zerosized && is_reg_zerosized)
{
need_copy = TRUE;
}
else if (!options->force_copy)
{
HardlinkResult hardlink_res = HARDLINK_RESULT_NOT_SUPPORTED;
@ -699,6 +732,7 @@ checkout_one_file_at (OstreeRepo *repo,
if (can_cache
&& !is_whiteout
&& !is_symlink
&& !is_reg_zerosized
&& need_copy
&& repo->mode == OSTREE_REPO_MODE_ARCHIVE
&& options->mode == OSTREE_REPO_CHECKOUT_MODE_USER)
@ -762,12 +796,12 @@ checkout_one_file_at (OstreeRepo *repo,
* succeeded at hardlinking above.
*/
if (options->no_copy_fallback)
g_assert (is_bare_user_symlink);
g_assert (is_bare_user_symlink || is_reg_zerosized);
if (!ostree_repo_load_file (repo, checksum, &input, NULL, &xattrs,
cancellable, error))
return FALSE;
if (!create_file_copy_from_input_at (repo, options, state, source_info, xattrs, input,
if (!create_file_copy_from_input_at (repo, options, state, checksum, source_info, xattrs, input,
destination_dfd, destination_name,
cancellable, error))
return glnx_prefix_error (error, "Copy checkout of %s to %s", checksum, destination_name);

View File

@ -245,16 +245,7 @@ commit_loose_regfile_object (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
/* We may be writing as root to a non-root-owned repository; if so,
* automatically inherit the non-root ownership.
*/
if (self->mode == OSTREE_REPO_MODE_ARCHIVE
&& self->target_owner_uid != -1)
{
if (fchown (tmpf->fd, self->target_owner_uid, self->target_owner_gid) < 0)
return glnx_throw_errno_prefix (error, "fchown");
}
else if (self->mode == OSTREE_REPO_MODE_BARE)
if (self->mode == OSTREE_REPO_MODE_BARE)
{
if (TEMP_FAILURE_RETRY (fchown (tmpf->fd, uid, gid)) < 0)
return glnx_throw_errno_prefix (error, "fchown");
@ -1336,18 +1327,6 @@ write_metadata_object (OstreeRepo *self,
gsize len;
const guint8 *bufp = g_bytes_get_data (buf, &len);
/* Do the size warning here, to avoid warning for already extant metadata */
if (G_UNLIKELY (len > OSTREE_MAX_METADATA_WARN_SIZE))
{
g_autofree char *metasize = g_format_size (len);
g_autofree char *warnsize = g_format_size (OSTREE_MAX_METADATA_WARN_SIZE);
g_autofree char *maxsize = g_format_size (OSTREE_MAX_METADATA_SIZE);
g_warning ("metadata object %s is %s, which is larger than the warning threshold of %s." \
" The hard limit on metadata size is %s. Put large content in the tree itself, not in metadata.",
actual_checksum,
metasize, warnsize, maxsize);
}
/* Write the metadata to a temporary file */
g_auto(GLnxTmpfile) tmpf = { 0, };
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (self), ".", O_WRONLY|O_CLOEXEC,
@ -1536,25 +1515,6 @@ devino_cache_lookup (OstreeRepo *self,
return dev_ino_val->checksum;
}
static guint64
min_free_space_calculate_reserved_blocks (OstreeRepo *self, struct statvfs *stvfsbuf)
{
guint64 reserved_blocks = 0;
if (self->min_free_space_mb > 0)
{
reserved_blocks = (self->min_free_space_mb << 20) / stvfsbuf->f_bsize;
}
else if (self->min_free_space_percent > 0)
{
/* Convert fragment to blocks to compute the total */
guint64 total_blocks = (stvfsbuf->f_frsize * stvfsbuf->f_blocks) / stvfsbuf->f_bsize;
reserved_blocks = ((double)total_blocks) * (self->min_free_space_percent/100.0);
}
return reserved_blocks;
}
/**
* ostree_repo_scan_hardlinks:
* @self: An #OstreeRepo
@ -1626,6 +1586,7 @@ ostree_repo_prepare_transaction (OstreeRepo *self,
GError **error)
{
g_autoptr(_OstreeRepoAutoTransaction) txn = NULL;
guint64 reserved_bytes = 0;
g_return_val_if_fail (self->in_transaction == FALSE, FALSE);
@ -1650,11 +1611,17 @@ ostree_repo_prepare_transaction (OstreeRepo *self,
g_mutex_lock (&self->txn_lock);
self->txn.blocksize = stvfsbuf.f_bsize;
guint64 reserved_blocks = min_free_space_calculate_reserved_blocks (self, &stvfsbuf);
if (!ostree_repo_get_min_free_space_bytes (self, &reserved_bytes, error))
{
g_mutex_unlock (&self->txn_lock);
return FALSE;
}
self->reserved_blocks = reserved_bytes / self->txn.blocksize;
/* Use the appropriate free block count if we're unprivileged */
guint64 bfree = (getuid () != 0 ? stvfsbuf.f_bavail : stvfsbuf.f_bfree);
if (bfree > reserved_blocks)
self->txn.max_blocks = bfree - reserved_blocks;
if (bfree > self->reserved_blocks)
self->txn.max_blocks = bfree - self->reserved_blocks;
else
{
self->cleanup_stagedir = TRUE;
@ -2290,25 +2257,6 @@ ostree_repo_abort_transaction (OstreeRepo *self,
return TRUE;
}
/* These limits were introduced since in some cases we may be processing
* malicious metadata, and we want to make disk space exhaustion attacks harder.
*/
static gboolean
metadata_size_valid (OstreeObjectType objtype,
gsize len,
GError **error)
{
if (G_UNLIKELY (len > OSTREE_MAX_METADATA_SIZE))
{
g_autofree char *input_bytes = g_format_size (len);
g_autofree char *max_bytes = g_format_size (OSTREE_MAX_METADATA_SIZE);
return glnx_throw (error, "Metadata object of type '%s' is %s; maximum metadata size is %s",
ostree_object_type_to_string (objtype), input_bytes, max_bytes);
}
return TRUE;
}
/**
* ostree_repo_write_metadata:
* @self: Repo
@ -2361,9 +2309,6 @@ ostree_repo_write_metadata (OstreeRepo *self,
normalized = g_variant_get_normal_form (object);
}
if (!metadata_size_valid (objtype, g_variant_get_size (normalized), error))
return FALSE;
/* For untrusted objects, verify their structure here */
if (expected_checksum)
{
@ -2401,9 +2346,6 @@ ostree_repo_write_metadata_stream_trusted (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
if (length > 0 && !metadata_size_valid (objtype, length, error))
return FALSE;
/* This is all pretty ridiculous, but we're keeping this API for backwards
* compatibility, it doesn't really need to be fast.
*/
@ -4305,11 +4247,12 @@ import_one_object_direct (OstreeRepo *dest_repo,
}
/* Don't want to copy xattrs for archive repos, nor for
* bare-user-only.
* bare-user-only. We also only do this for content
* objects.
*/
const gboolean src_is_bare_or_bare_user =
G_IN_SET (src_repo->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER);
if (src_is_bare_or_bare_user)
if (src_is_bare_or_bare_user && !OSTREE_OBJECT_TYPE_IS_META(objtype))
{
g_autoptr(GVariant) xattrs = NULL;

View File

@ -509,6 +509,16 @@ fill_refs_and_checksums_from_summary (GVariant *summary,
return TRUE;
}
static gboolean
remove_null_checksum_refs_cb (gpointer key,
gpointer value,
gpointer user_data)
{
const char *checksum = value;
return (checksum == NULL);
}
/* Given a summary file (@summary_bytes), extract the refs it lists, and use that
* to fill in the checksums in the @supported_ref_to_checksum map. This includes
* the main refs list in the summary, and the map of collection IDs to further
@ -520,12 +530,11 @@ fill_refs_and_checksums_from_summary (GVariant *summary,
static gboolean
get_refs_and_checksums_from_summary (GBytes *summary_bytes,
GHashTable *supported_ref_to_checksum /* (element-type OstreeCollectionRef utf8) */,
OstreeRemote *remote,
GError **error)
{
g_autoptr(GVariant) summary = g_variant_ref_sink (g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT, summary_bytes, FALSE));
GHashTableIter iter;
const OstreeCollectionRef *ref;
const gchar *checksum;
guint removed_refs;
if (!g_variant_is_normal_form (summary))
{
@ -544,22 +553,22 @@ get_refs_and_checksums_from_summary (GBytes *summary_bytes,
if (!fill_refs_and_checksums_from_summary (summary, supported_ref_to_checksum, error))
return FALSE;
/* Check that at least one of the refs has a non-%NULL checksum set, otherwise
* we can discard this peer. */
g_hash_table_iter_init (&iter, supported_ref_to_checksum);
while (g_hash_table_iter_next (&iter,
(gpointer *) &ref,
(gpointer *) &checksum))
{
if (checksum != NULL)
return TRUE;
}
removed_refs = g_hash_table_foreach_remove (supported_ref_to_checksum, remove_null_checksum_refs_cb, NULL);
if (removed_refs > 0)
g_debug ("Removed %d refs from the list resolved from %s (possibly bloom filter false positives)",
removed_refs, remote->name);
/* If none of the refs had a non-%NULL checksum set, we can discard this peer. */
if (g_hash_table_size (supported_ref_to_checksum) == 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"No matching refs were found in the summary file");
return FALSE;
}
return TRUE;
}
/* Download the summary file from @remote, and return the bytes of the file in
* @out_summary_bytes. This will return %TRUE and set @out_summary_bytes to %NULL
* if the summary file does not exist. */
@ -661,7 +670,7 @@ get_checksums (OstreeRepoFinderAvahi *finder,
return FALSE;
}
return get_refs_and_checksums_from_summary (summary_bytes, supported_ref_to_checksum, error);
return get_refs_and_checksums_from_summary (summary_bytes, supported_ref_to_checksum, remote, error);
}
/* Build some #OstreeRepoFinderResults out of the given #OstreeAvahiService by

View File

@ -149,10 +149,9 @@ struct OstreeRepo {
dev_t device;
ino_t inode;
uid_t owner_uid; /* Cache of repo's owner uid */
uid_t target_owner_uid; /* Ensure files are chowned to this uid/gid */
gid_t target_owner_gid;
guint min_free_space_percent; /* See the min-free-space-percent config option */
guint64 min_free_space_mb; /* See the min-free-space-size config option */
guint64 reserved_blocks;
gboolean cleanup_stagedir;
guint test_error_flags; /* OstreeRepoTestErrorFlags */
@ -169,6 +168,7 @@ struct OstreeRepo {
gint lock_timeout_seconds;
guint64 payload_link_threshold;
gint fs_support_reflink; /* The underlying filesystem has support for ioctl (FICLONE..) */
gchar **repo_finders;
OstreeRepo *parent_repo;
};

View File

@ -150,6 +150,7 @@ typedef struct {
gboolean timestamp_check; /* Verify commit timestamps */
int maxdepth;
guint64 max_metadata_size;
guint64 start_time;
gboolean is_mirror;
@ -2193,7 +2194,7 @@ start_fetch (OtPullData *pull_data,
if (expected_max_size_p)
expected_max_size = *expected_max_size_p;
else if (OSTREE_OBJECT_TYPE_IS_META (objtype))
expected_max_size = OSTREE_MAX_METADATA_SIZE;
expected_max_size = pull_data->max_metadata_size;
else
expected_max_size = 0;
@ -3488,6 +3489,7 @@ initiate_request (OtPullData *pull_data,
* * require-static-deltas (b): Require static deltas
* * override-commit-ids (as): Array of specific commit IDs to fetch for refs
* * timestamp-check (b): Verify commit timestamps are newer than current (when pulling via ref); Since: 2017.11
* * metadata-size-restriction (t): Restrict metadata objects to a maximum number of bytes; 0 to disable. Since: 2018.9
* * dry-run (b): Only print information on what will be downloaded (requires static deltas)
* * override-url (s): Fetch objects from this URL if remote specifies no metalink in options
* * inherit-transaction (b): Don't initiate, finish or abort a transaction, useful to do multiple pulls in one transaction.
@ -3543,6 +3545,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
*/
const char *the_ref_to_fetch = NULL;
/* Default */
pull_data->max_metadata_size = OSTREE_MAX_METADATA_SIZE;
if (options)
{
int flags_i = OSTREE_REPO_PULL_FLAGS_NONE;
@ -3570,6 +3575,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
(void) g_variant_lookup (options, "update-frequency", "u", &update_frequency);
(void) g_variant_lookup (options, "localcache-repos", "^a&s", &opt_localcache_repos);
(void) g_variant_lookup (options, "timestamp-check", "b", &pull_data->timestamp_check);
(void) g_variant_lookup (options, "max-metadata-size", "t", &pull_data->max_metadata_size);
(void) g_variant_lookup (options, "append-user-agent", "s", &pull_data->append_user_agent);
opt_n_network_retries_set =
g_variant_lookup (options, "n-network-retries", "u", &pull_data->n_network_retries);
@ -4993,24 +4999,34 @@ ostree_repo_find_remotes_async (OstreeRepo *self,
/* Are we using #OstreeRepoFinders provided by the user, or the defaults? */
if (finders == NULL)
{
guint finder_index = 0;
#ifdef HAVE_AVAHI
guint avahi_index;
GMainContext *context = g_main_context_get_thread_default ();
g_autoptr(GError) local_error = NULL;
#endif /* HAVE_AVAHI */
finder_config = OSTREE_REPO_FINDER (ostree_repo_finder_config_new ());
finder_mount = OSTREE_REPO_FINDER (ostree_repo_finder_mount_new (NULL));
if (g_strv_contains ((const char * const *)self->repo_finders, "config"))
default_finders[finder_index++] = finder_config = OSTREE_REPO_FINDER (ostree_repo_finder_config_new ());
if (g_strv_contains ((const char * const *)self->repo_finders, "mount"))
default_finders[finder_index++] = finder_mount = OSTREE_REPO_FINDER (ostree_repo_finder_mount_new (NULL));
#ifdef HAVE_AVAHI
finder_avahi = OSTREE_REPO_FINDER (ostree_repo_finder_avahi_new (context));
if (g_strv_contains ((const char * const *)self->repo_finders, "lan"))
{
avahi_index = finder_index;
default_finders[finder_index++] = finder_avahi = OSTREE_REPO_FINDER (ostree_repo_finder_avahi_new (context));
}
#endif /* HAVE_AVAHI */
default_finders[0] = finder_config;
default_finders[1] = finder_mount;
default_finders[2] = finder_avahi;
/* self->repo_finders is guaranteed to be non-empty */
g_assert (default_finders != NULL);
finders = default_finders;
#ifdef HAVE_AVAHI
if (finder_avahi != NULL)
{
ostree_repo_finder_avahi_start (OSTREE_REPO_FINDER_AVAHI (finder_avahi),
&local_error);
@ -5030,9 +5046,10 @@ ostree_repo_find_remotes_async (OstreeRepo *self,
else
g_warning ("Avahi finder failed abnormally; removing it: %s", local_error->message);
default_finders[2] = NULL;
default_finders[avahi_index] = NULL;
g_clear_object (&finder_avahi);
}
}
#endif /* HAVE_AVAHI */
}

View File

@ -90,17 +90,19 @@ G_STATIC_ASSERT(sizeof(OstreeRepoPruneOptions) ==
* The #OstreeRepo is like git, a content-addressed object store.
* Unlike git, it records uid, gid, and extended attributes.
*
* There are three possible "modes" for an #OstreeRepo;
* %OSTREE_REPO_MODE_BARE is very simple - content files are
* represented exactly as they are, and checkouts are just hardlinks.
* %OSTREE_REPO_MODE_BARE_USER is similar, except the uid/gids are not
* set on the files, and checkouts as hardlinks hardlinks work only for user checkouts.
* A %OSTREE_REPO_MODE_ARCHIVE_Z2 repository in contrast stores
* There are four possible "modes" for an #OstreeRepo; %OSTREE_REPO_MODE_BARE
* is very simple - content files are represented exactly as they are, and
* checkouts are just hardlinks. %OSTREE_REPO_MODE_BARE_USER is similar, except
* the uid/gids are not set on the files, and checkouts as hardlinks work only
* for user checkouts. %OSTREE_REPO_MODE_BARE_USER_ONLY is the same as
* BARE_USER, but all metadata is not stored, so it can only be used for user
* checkouts. This mode does not require xattrs. A %OSTREE_REPO_MODE_ARCHIVE
* (also known as %OSTREE_REPO_MODE_ARCHIVE_Z2) repository in contrast stores
* content files zlib-compressed. It is suitable for non-root-owned
* repositories that can be served via a static HTTP server.
*
* Creating an #OstreeRepo does not invoke any file I/O, and thus needs
* to be initialized, either from an existing contents or with a new
* to be initialized, either from existing contents or as a new
* repository. If you have an existing repo, use ostree_repo_open()
* to load it from disk and check its validity. To initialize a new
* repository in the given filepath, use ostree_repo_create() instead.
@ -452,9 +454,9 @@ pop_repo_lock (OstreeRepo *self,
* state is not changed and the stack is simply updated.
*
* ostree_repo_lock_push() waits for the lock depending on the repository's
* lock-timeout configuration. When lock-timeout is -1, a blocking lock is
* lock-timeout-secs configuration. When lock-timeout-secs is -1, a blocking lock is
* attempted. Otherwise, the lock is taken non-blocking and
* ostree_repo_lock_push() will sleep synchronously up to lock-timeout seconds
* ostree_repo_lock_push() will sleep synchronously up to lock-timeout-secs seconds
* attempting to acquire the lock. If the lock cannot be acquired within the
* timeout, a %G_IO_ERROR_WOULD_BLOCK error is returned.
*
@ -542,9 +544,9 @@ _ostree_repo_lock_push (OstreeRepo *self,
* lock.
*
* ostree_repo_lock_pop() waits for the lock depending on the repository's
* lock-timeout configuration. When lock-timeout is -1, a blocking lock is
* lock-timeout-secs configuration. When lock-timeout-secs is -1, a blocking lock is
* attempted. Otherwise, the lock is removed non-blocking and
* ostree_repo_lock_pop() will sleep synchronously up to lock-timeout seconds
* ostree_repo_lock_pop() will sleep synchronously up to lock-timeout-secs seconds
* attempting to remove the lock. If the lock cannot be removed within the
* timeout, a %G_IO_ERROR_WOULD_BLOCK error is returned.
*
@ -1033,6 +1035,7 @@ ostree_repo_finalize (GObject *object)
g_mutex_clear (&self->cache_lock);
g_mutex_clear (&self->txn_lock);
g_free (self->collection_id);
g_strfreev (self->repo_finders);
g_clear_pointer (&self->remotes, g_hash_table_destroy);
g_mutex_clear (&self->remotes_lock);
@ -2653,6 +2656,37 @@ get_remotes_d_dir (OstreeRepo *self,
return g_file_resolve_relative_path (sysroot, SYSCONF_REMOTES);
}
static gboolean
min_free_space_calculate_reserved_bytes (OstreeRepo *self, guint64 *bytes, GError **error)
{
guint64 reserved_bytes = 0;
struct statvfs stvfsbuf;
if (TEMP_FAILURE_RETRY (fstatvfs (self->repo_dir_fd, &stvfsbuf)) < 0)
return glnx_throw_errno_prefix (error, "fstatvfs");
if (self->min_free_space_mb > 0)
{
if (self->min_free_space_mb > (G_MAXUINT64 >> 20))
return glnx_throw (error, "min-free-space value is greater than the maximum allowed value of %" G_GUINT64_FORMAT " bytes",
(G_MAXUINT64 >> 20));
reserved_bytes = self->min_free_space_mb << 20;
}
else if (self->min_free_space_percent > 0)
{
if (stvfsbuf.f_frsize > (G_MAXUINT64 / stvfsbuf.f_blocks))
return glnx_throw (error, "Filesystem's size is greater than the maximum allowed value of %" G_GUINT64_FORMAT " bytes",
(G_MAXUINT64 / stvfsbuf.f_blocks));
guint64 total_bytes = (stvfsbuf.f_frsize * stvfsbuf.f_blocks);
reserved_bytes = ((double)total_bytes) * (self->min_free_space_percent/100.0);
}
*bytes = reserved_bytes;
return TRUE;
}
static gboolean
min_free_space_size_validate_and_convert (OstreeRepo *self,
const char *min_free_space_size_str,
@ -2799,7 +2833,7 @@ reload_core_config (OstreeRepo *self,
&lock_timeout_seconds, error))
return FALSE;
self->lock_timeout_seconds = g_ascii_strtoull (lock_timeout_seconds, NULL, 10);
self->lock_timeout_seconds = g_ascii_strtoll (lock_timeout_seconds, NULL, 10);
}
}
@ -2905,6 +2939,40 @@ reload_core_config (OstreeRepo *self,
self->payload_link_threshold = g_ascii_strtoull (payload_threshold, NULL, 10);
}
{ g_auto(GStrv) configured_finders = NULL;
g_autoptr(GError) local_error = NULL;
configured_finders = g_key_file_get_string_list (self->config, "core", "default-repo-finders",
NULL, &local_error);
if (g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
g_clear_error (&local_error);
else if (local_error != NULL)
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
if (configured_finders != NULL && *configured_finders == NULL)
return glnx_throw (error, "Invalid empty default-repo-finders configuration");
for (char **iter = configured_finders; iter && *iter; iter++)
{
const char *repo_finder = *iter;
if (strcmp (repo_finder, "config") != 0 &&
strcmp (repo_finder, "lan") != 0 &&
strcmp (repo_finder, "mount") != 0)
return glnx_throw (error, "Invalid configured repo-finder '%s'", repo_finder);
}
/* Fall back to a default set of finders */
if (configured_finders == NULL)
configured_finders = g_strsplit ("config;mount", ";", -1);
g_clear_pointer (&self->repo_finders, g_strfreev);
self->repo_finders = g_steal_pointer (&configured_finders);
}
return TRUE;
}
@ -3047,16 +3115,6 @@ ostree_repo_open (OstreeRepo *self,
return FALSE;
self->owner_uid = stbuf.st_uid;
if (stbuf.st_uid != getuid () || stbuf.st_gid != getgid ())
{
self->target_owner_uid = stbuf.st_uid;
self->target_owner_gid = stbuf.st_gid;
}
else
{
self->target_owner_uid = self->target_owner_gid = -1;
}
if (self->writable)
{
/* Always try to recreate the tmpdir to be nice to people
@ -3292,6 +3350,30 @@ ostree_repo_get_mode (OstreeRepo *self)
return self->mode;
}
/**
* ostree_repo_get_min_free_space:
* @self: Repo
* @out_reserved_bytes: (out): Location to store the result
* @error: Return location for a #GError
*
* It can be used to query the value (in bytes) of min-free-space-* config option.
*
* Returns: %TRUE on success, %FALSE otherwise.
* Since: 2018.9
*/
gboolean
ostree_repo_get_min_free_space_bytes (OstreeRepo *self, guint64 *out_reserved_bytes, GError **error)
{
g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE);
g_return_val_if_fail (out_reserved_bytes != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!min_free_space_calculate_reserved_bytes (self, out_reserved_bytes, error))
return glnx_prefix_error (error, "Error calculating min-free-space bytes");
return TRUE;
}
/**
* ostree_repo_get_parent:
* @self: Repo
@ -5868,3 +5950,22 @@ ostree_repo_set_collection_id (OstreeRepo *self,
return TRUE;
}
/**
* ostree_repo_get_default_repo_finders:
* @self: an #OstreeRepo
*
* Get the set of default repo finders configured. See the documentation for
* the "core.default-repo-finders" config key.
*
* Returns: (array zero-terminated=1) (element-type utf8):
* %NULL-terminated array of strings.
* Since: 2018.9
*/
const gchar * const *
ostree_repo_get_default_repo_finders (OstreeRepo *self)
{
g_return_val_if_fail (OSTREE_IS_REPO (self), NULL);
return (const gchar * const *)self->repo_finders;
}

View File

@ -112,6 +112,9 @@ gboolean ostree_repo_set_collection_id (OstreeRepo *self,
const gchar *collection_id,
GError **error);
_OSTREE_PUBLIC
const gchar * const * ostree_repo_get_default_repo_finders (OstreeRepo *self);
_OSTREE_PUBLIC
GFile * ostree_repo_get_path (OstreeRepo *self);
@ -127,6 +130,10 @@ gboolean ostree_repo_equal (OstreeRepo *a,
_OSTREE_PUBLIC
OstreeRepoMode ostree_repo_get_mode (OstreeRepo *self);
_OSTREE_PUBLIC
gboolean ostree_repo_get_min_free_space_bytes (OstreeRepo *self,
guint64 *out_reserved_bytes,
GError **error);
_OSTREE_PUBLIC
GKeyFile * ostree_repo_get_config (OstreeRepo *self);
@ -929,7 +936,8 @@ typedef struct {
gboolean no_copy_fallback;
gboolean force_copy; /* Since: 2017.6 */
gboolean bareuseronly_dirs; /* Since: 2017.7 */
gboolean unused_bools[5];
gboolean force_copy_zerosized; /* Since: 2018.9 */
gboolean unused_bools[4];
/* 4 byte hole on 64 bit */
const char *subpath;
@ -1395,6 +1403,29 @@ gboolean ostree_repo_regenerate_summary (OstreeRepo *self,
*/
#define OSTREE_REPO_METADATA_REF "ostree-metadata"
/**
* OSTREE_META_KEY_DEPLOY_COLLECTION_ID:
*
* GVariant type `s`. This key can be used in the repo metadata which is stored
* in OSTREE_REPO_METADATA_REF as well as in the summary. The semantics of this
* are that the remote repository wants clients to update their remote config
* to add this collection ID (clients can't do P2P operations involving a
* remote without a collection ID configured on it, even if one is configured
* on the server side). Clients must never change or remove a collection ID
* already set in their remote config.
*
* Currently, OSTree does not implement changing a remote config based on this
* key, but it may do so in a later release, and until then clients such as
* Flatpak may implement it.
*
* This is a replacement for the similar metadata key implemented by flatpak,
* `xa.collection-id`, which is now deprecated as clients which supported it had
* bugs with their P2P implementations.
*
* Since: 2018.9
*/
#define OSTREE_META_KEY_DEPLOY_COLLECTION_ID "ostree.deploy-collection-id"
G_END_DECLS

View File

@ -52,6 +52,7 @@
#define OSTREE_VARRELABEL_ID SD_ID128_MAKE(da,67,9b,08,ac,d3,45,04,b7,89,d9,6f,81,8e,a7,81)
#define OSTREE_CONFIGMERGE_ID SD_ID128_MAKE(d3,86,3b,ae,c1,3e,44,49,ab,03,84,68,4a,8a,f3,a7)
#define OSTREE_DEPLOYMENT_COMPLETE_ID SD_ID128_MAKE(dd,44,0e,3e,54,90,83,b6,3d,0e,fc,7d,c1,52,55,f1)
#define OSTREE_DEPLOYMENT_FINALIZING_ID SD_ID128_MAKE(e8,64,6c,d6,3d,ff,46,25,b7,79,09,a8,e7,a4,09,94)
#endif
/*
@ -2509,6 +2510,47 @@ sysroot_initialize_deployment (OstreeSysroot *self,
return TRUE;
}
/* Get a directory fd for the /var of @deployment.
* Before we supported having /var be a separate mount point,
* this was easy. However, as https://github.com/ostreedev/ostree/issues/1729
* raised, in the primary case where we're
* doing a new deployment for the booted stateroot,
* we need to use /var/. This code doesn't correctly
* handle the case of `ostree admin --sysroot upgrade`,
* nor (relatedly) the case of upgrading a separate stateroot.
*/
static gboolean
get_var_dfd (OstreeSysroot *self,
int osdeploy_dfd,
OstreeDeployment *deployment,
int *ret_fd,
GError **error)
{
const char *booted_stateroot =
self->booted_deployment ? ostree_deployment_get_osname (self->booted_deployment) : NULL;
int base_dfd;
const char *base_path;
/* The common case is when we're doing a new deployment for the same stateroot (osname).
* If we have a separate mounted /var, then we need to use it - the /var in the
* stateroot will probably just be an empty directory.
*
* If the stateroot doesn't match, just fall back to /var in the target's stateroot.
*/
if (g_strcmp0 (booted_stateroot, ostree_deployment_get_osname (deployment)) == 0)
{
base_dfd = AT_FDCWD;
base_path = "/var";
}
else
{
base_dfd = osdeploy_dfd;
base_path = "var";
}
return glnx_opendirat (base_dfd, base_path, TRUE, ret_fd, error);
}
static gboolean
sysroot_finalize_deployment (OstreeSysroot *self,
OstreeDeployment *deployment,
@ -2547,6 +2589,9 @@ sysroot_finalize_deployment (OstreeSysroot *self,
glnx_autofd int os_deploy_dfd = -1;
if (!glnx_opendirat (self->sysroot_fd, osdeploypath, TRUE, &os_deploy_dfd, error))
return FALSE;
glnx_autofd int var_dfd = -1;
if (!get_var_dfd (self, os_deploy_dfd, deployment, &var_dfd, error))
return FALSE;
/* Ensure that the new deployment does not have /etc/.updated or
* /var/.updated so that systemd ConditionNeedsUpdate=/etc|/var services run
@ -2554,7 +2599,7 @@ sysroot_finalize_deployment (OstreeSysroot *self,
*/
if (!ot_ensure_unlinked_at (deployment_dfd, "etc/.updated", error))
return FALSE;
if (!ot_ensure_unlinked_at (os_deploy_dfd, "var/.updated", error))
if (!ot_ensure_unlinked_at (var_dfd, ".updated", error))
return FALSE;
g_autoptr(OstreeSePolicy) sepolicy = ostree_sepolicy_new_at (deployment_dfd, cancellable, error);
@ -2716,6 +2761,10 @@ ostree_sysroot_stage_tree (OstreeSysroot *self,
if (booted_deployment == NULL)
return glnx_throw (error, "Cannot stage a deployment when not currently booted into an OSTree system");
/* This is used by the testsuite to exercise the path unit, until it becomes the default
* (which is pending on the preset making it everywhere). */
if ((self->debug_flags & OSTREE_SYSROOT_DEBUG_TEST_STAGED_PATH) == 0)
{
/* This is a bit of a hack. When adding a new service we have to end up getting
* into the presets for downstream distros; see e.g. https://src.fedoraproject.org/rpms/ostree/pull-request/7
*
@ -2728,6 +2777,11 @@ ostree_sysroot_stage_tree (OstreeSysroot *self,
return FALSE;
if (!g_spawn_check_exit_status (estatus, error))
return FALSE;
}
else
{
g_print ("test-staged-path: Not running `systemctl start`\n");
} /* OSTREE_SYSROOT_DEBUG_TEST_STAGED_PATH */
g_autoptr(OstreeDeployment) deployment = NULL;
if (!sysroot_initialize_deployment (self, osname, revision, origin, override_kernel_argv,
@ -2818,6 +2872,21 @@ _ostree_sysroot_finalize_staged (OstreeSysroot *self,
if (!self->staged_deployment)
return TRUE;
/* Notice we send this *after* the trivial `return TRUE` above; this msg implies we've
* committed to finalizing the deployment. */
#ifdef HAVE_LIBSYSTEMD
sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR,
SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_FINALIZING_ID),
"MESSAGE=Finalizing staged deployment",
"OSTREE_OSNAME=%s",
ostree_deployment_get_osname (self->staged_deployment),
"OSTREE_CHECKSUM=%s",
ostree_deployment_get_csum (self->staged_deployment),
"OSTREE_DEPLOYSERIAL=%u",
ostree_deployment_get_deployserial (self->staged_deployment),
NULL);
#endif
g_assert (self->staged_deployment_data);
g_autoptr(OstreeDeployment) merge_deployment = NULL;

View File

@ -36,6 +36,9 @@ typedef enum {
OSTREE_SYSROOT_DEBUG_NO_XATTRS = 1 << 1,
/* https://github.com/ostreedev/ostree/pull/1049 */
OSTREE_SYSROOT_DEBUG_TEST_FIFREEZE = 1 << 2,
/* This is a temporary flag until we fully drop the explicit `systemctl start
* ostree-finalize-staged.service` so that tests can exercise the new path unit. */
OSTREE_SYSROOT_DEBUG_TEST_STAGED_PATH = 1 << 3,
} OstreeSysrootDebugFlags;
/**

View File

@ -189,6 +189,7 @@ ostree_sysroot_init (OstreeSysroot *self)
{ "mutable-deployments", OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS },
{ "test-fifreeze", OSTREE_SYSROOT_DEBUG_TEST_FIFREEZE },
{ "no-xattrs", OSTREE_SYSROOT_DEBUG_NO_XATTRS },
{ "test-staged-path", OSTREE_SYSROOT_DEBUG_TEST_STAGED_PATH },
};
self->debug_flags = g_parse_debug_string (g_getenv ("OSTREE_SYSROOT_DEBUG"),
@ -376,12 +377,11 @@ _ostree_sysroot_read_current_subbootversion (OstreeSysroot *self,
g_autofree char *ostree_bootdir_name = g_strdup_printf ("ostree/boot.%d", bootversion);
struct stat stbuf;
if (fstatat (self->sysroot_fd, ostree_bootdir_name, &stbuf, AT_SYMLINK_NOFOLLOW) != 0)
{
if (!glnx_fstatat_allow_noent (self->sysroot_fd, ostree_bootdir_name, &stbuf, AT_SYMLINK_NOFOLLOW, error))
return FALSE;
if (errno == ENOENT)
{
*out_subbootversion = 0;
else
return glnx_throw_errno (error);
}
else
{
@ -499,10 +499,10 @@ read_current_bootversion (OstreeSysroot *self,
int ret_bootversion;
struct stat stbuf;
if (fstatat (self->sysroot_fd, "boot/loader", &stbuf, AT_SYMLINK_NOFOLLOW) != 0)
if (!glnx_fstatat_allow_noent (self->sysroot_fd, "boot/loader", &stbuf, AT_SYMLINK_NOFOLLOW, error))
return FALSE;
if (errno == ENOENT)
{
if (errno != ENOENT)
return glnx_throw_errno (error);
ret_bootversion = 0;
}
else
@ -613,6 +613,10 @@ parse_deployment (OstreeSysroot *self,
error))
return FALSE;
g_autofree char *errprefix =
g_strdup_printf ("Parsing deployment %i in stateroot '%s'", treebootserial, osname);
GLNX_AUTO_PREFIX_ERROR(errprefix, error);
const char *relative_boot_link = boot_link;
if (*relative_boot_link == '/')
relative_boot_link++;
@ -976,10 +980,11 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self,
/* Otherwise - check for /sysroot which should only exist in a deployment,
* not in ${sysroot} (a metavariable for the real physical root).
*/
else if (fstatat (self->sysroot_fd, "sysroot", &stbuf, 0) < 0)
else
{
if (errno != ENOENT)
return glnx_throw_errno_prefix (error, "fstatat");
if (!glnx_fstatat_allow_noent (self->sysroot_fd, "sysroot", &stbuf, 0, error))
return FALSE;
if (errno == ENOENT)
self->is_physical = TRUE;
}
/* Otherwise, the default is FALSE */

View File

@ -43,7 +43,7 @@
*
* Since: 2017.4
*/
#define OSTREE_RELEASE_VERSION (8)
#define OSTREE_RELEASE_VERSION (9)
/**
* OSTREE_VERSION
@ -52,7 +52,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION (2018.8)
#define OSTREE_VERSION (2018.9)
/**
* OSTREE_VERSION_S:
@ -62,7 +62,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION_S "2018.8"
#define OSTREE_VERSION_S "2018.9"
#define OSTREE_ENCODE_VERSION(year,release) \
((year) << 16 | (release))

View File

@ -45,6 +45,7 @@ static char *opt_from_file;
static gboolean opt_disable_fsync;
static gboolean opt_require_hardlinks;
static gboolean opt_force_copy;
static gboolean opt_force_copy_zerosized;
static gboolean opt_bareuseronly_dirs;
static char *opt_skiplist_file;
static char *opt_selinux_policy;
@ -84,6 +85,7 @@ static GOptionEntry options[] = {
{ "from-file", 0, 0, G_OPTION_ARG_STRING, &opt_from_file, "Process many checkouts from input file", "FILE" },
{ "fsync", 0, 0, G_OPTION_ARG_CALLBACK, parse_fsync_cb, "Specify how to invoke fsync()", "POLICY" },
{ "require-hardlinks", 'H', 0, G_OPTION_ARG_NONE, &opt_require_hardlinks, "Do not fall back to full copies if hardlinking fails", NULL },
{ "force-copy-zerosized", 'z', 0, G_OPTION_ARG_NONE, &opt_force_copy_zerosized, "Do not hardlink zero-sized files", NULL },
{ "force-copy", 'C', 0, G_OPTION_ARG_NONE, &opt_force_copy, "Never hardlink (but may reflink if available)", NULL },
{ "bareuseronly-dirs", 'M', 0, G_OPTION_ARG_NONE, &opt_bareuseronly_dirs, "Suppress mode bits outside of 0775 for directories (suid, world writable, etc.)", NULL },
{ "skip-list", 0, 0, G_OPTION_ARG_FILENAME, &opt_skiplist_file, "File containing list of files to skip", "PATH" },
@ -130,7 +132,8 @@ process_one_checkout (OstreeRepo *repo,
* convenient infrastructure for testing C APIs with data.
*/
if (opt_disable_cache || opt_whiteouts || opt_require_hardlinks ||
opt_union_add || opt_force_copy || opt_bareuseronly_dirs || opt_union_identical ||
opt_union_add || opt_force_copy || opt_force_copy_zerosized ||
opt_bareuseronly_dirs || opt_union_identical ||
opt_skiplist_file || opt_selinux_policy || opt_selinux_prefix)
{
OstreeRepoCheckoutAtOptions options = { 0, };
@ -218,6 +221,7 @@ process_one_checkout (OstreeRepo *repo,
options.no_copy_fallback = opt_require_hardlinks;
options.force_copy = opt_force_copy;
options.force_copy_zerosized = opt_force_copy_zerosized;
options.bareuseronly_dirs = opt_bareuseronly_dirs;
if (!ostree_repo_checkout_at (repo, &options,

View File

@ -33,11 +33,13 @@
static gboolean opt_disable_fsync = FALSE;
static char *opt_destination_repo = NULL;
static char *opt_commit = NULL;
static GOptionEntry options[] =
{
{ "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL },
{ "destination-repo", 0, 0, G_OPTION_ARG_FILENAME, &opt_destination_repo, "Use custom repository directory within the mount", "DEST" },
{ "commit", 0, 0, G_OPTION_ARG_STRING, &opt_commit, "Pull a specific commit (only works when a single ref is specified)", "COMMIT" },
{ NULL }
};
@ -78,6 +80,12 @@ ostree_builtin_create_usb (int argc,
return FALSE;
}
if (opt_commit && argc > 4)
{
ot_util_usage_error (context, "The --commit option can only be used when a single COLLECTION-ID REF pair is specified", error);
return FALSE;
}
/* Open the USB stick, which must exist. Allow automounting and following symlinks. */
const char *mount_root_path = argv[1];
struct stat mount_root_stbuf;
@ -102,21 +110,17 @@ ostree_builtin_create_usb (int argc,
/* Open the destination repository on the USB stick or create it if it doesnt exist.
* Check its below @mount_root_path, and that its not the same as the source
* repository.
*
* If the destination file system supports xattrs (for example, ext4), we use
* a BARE_USER repository; if it doesnt (for example, FAT), we use ARCHIVE.
* In either case, we want a lossless repository. */
* repository. */
const char *dest_repo_path = (opt_destination_repo != NULL) ? opt_destination_repo : ".ostree/repo";
if (!glnx_shutil_mkdir_p_at (mount_root_dfd, dest_repo_path, 0755, cancellable, error))
return FALSE;
OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER;
if (TEMP_FAILURE_RETRY (fgetxattr (mount_root_dfd, "user.test", NULL, 0)) < 0 &&
(errno == ENOTSUP || errno == EOPNOTSUPP))
mode = OSTREE_REPO_MODE_ARCHIVE;
/* Always use the archive repo mode, which works on FAT file systems that
* don't support xattrs, compresses files to save space, doesn't store
* permission info directly in the file attributes, and is at least sometimes
* more performant than bare-user */
OstreeRepoMode mode = OSTREE_REPO_MODE_ARCHIVE;
g_debug ("%s: Creating repository in mode %u", G_STRFUNC, mode);
@ -158,7 +162,7 @@ ostree_builtin_create_usb (int argc,
const OstreeCollectionRef *ref = g_ptr_array_index (refs, i);
g_variant_builder_add (&refs_builder, "(sss)",
ref->collection_id, ref->ref_name, "");
ref->collection_id, ref->ref_name, opt_commit ?: "");
}
{

View File

@ -146,8 +146,10 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
/* If we're doing aliasing, we need the full list of aliases mostly to allow
* replacing existing aliases.
* If we are deleting a ref, we want to make sure that it doesn't have
* any corresponding aliases.
*/
if (opt_alias)
if (opt_alias || opt_delete)
{
if (!ostree_repo_list_refs_ext (repo, NULL, &ref_aliases,
OSTREE_REPO_LIST_REFS_EXT_ALIASES,
@ -246,6 +248,17 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
if (!ostree_parse_refspec (refspec, &remote, &ref, error))
goto out;
/* Look for alias if it exists for a ref we want to delete */
GLNX_HASH_TABLE_FOREACH_KV (ref_aliases, const char *,
ref_alias, const char *, value)
{
if (!strcmp (ref, value))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Ref '%s' has an active alias: '%s'", ref, ref_alias);
goto out;
}
}
if (!ostree_repo_set_ref_immediate (repo, remote, ref, NULL,
cancellable, error))
goto out;

View File

@ -25,6 +25,7 @@
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <stdio.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
@ -628,10 +629,7 @@ rofs_parse_opt (void *data, const char *arg, int key,
{
basefd = openat (AT_FDCWD, arg, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
if (basefd == -1)
{
perror ("openat");
exit (EXIT_FAILURE);
}
err (1, "opening rootfs %s", arg);
return 0;
}
else

View File

@ -39,13 +39,40 @@
#include "ostree-mount-util.h"
static void
do_remount (const char *target)
{
struct stat stbuf;
if (lstat (target, &stbuf) < 0)
return;
/* Silently ignore symbolic links; we expect these to point to
* /sysroot, and thus there isn't a bind mount there.
*/
if (S_ISLNK (stbuf.st_mode))
return;
/* If not a mountpoint, skip it */
struct statvfs stvfsbuf;
if (statvfs (target, &stvfsbuf) == -1)
return;
/* If no read-only flag, skip it */
if ((stvfsbuf.f_flag & ST_RDONLY) == 0)
return;
/* It's a mounted, read-only fs; remount it */
if (mount (target, target, NULL, MS_REMOUNT | MS_SILENT, NULL) < 0)
{
/* Also ignore EINVAL - if the target isn't a mountpoint
* already, then assume things are OK.
*/
if (errno != EINVAL)
err (EXIT_FAILURE, "failed to remount %s", target);
}
else
printf ("Remounted: %s\n", target);
}
int
main(int argc, char *argv[])
{
const char *remounts[] = { "/sysroot", "/var", NULL };
struct stat stbuf;
int i;
/* When systemd is in use this is normally created via the generator, but
* we ensure it's created here as well for redundancy.
*/
@ -65,39 +92,11 @@ main(int argc, char *argv[])
/* If / isn't writable, don't do any remounts; we don't want
* to clear the readonly flag in that case.
*/
exit (EXIT_SUCCESS);
}
for (i = 0; remounts[i] != NULL; i++)
{
const char *target = remounts[i];
if (lstat (target, &stbuf) < 0)
continue;
/* Silently ignore symbolic links; we expect these to point to
* /sysroot, and thus there isn't a bind mount there.
*/
if (S_ISLNK (stbuf.st_mode))
continue;
/* If not a mountpoint, skip it */
struct statvfs stvfsbuf;
if (statvfs (target, &stvfsbuf) == -1)
continue;
/* If no read-only flag, skip it */
if ((stvfsbuf.f_flag & ST_RDONLY) == 0)
continue;
/* It's a mounted, read-only fs; remount it */
if (mount (target, target, NULL, MS_REMOUNT | MS_SILENT, NULL) < 0)
{
/* Also ignore EINVAL - if the target isn't a mountpoint
* already, then assume things are OK.
*/
if (errno != EINVAL)
err (EXIT_FAILURE, "failed to remount %s", target);
}
else
printf ("Remounted: %s\n", target);
}
do_remount ("/sysroot");
do_remount ("/var");
exit (EXIT_SUCCESS);
}

View File

@ -21,7 +21,7 @@
set -euo pipefail
echo "1..$((83 + ${extra_basic_tests:-0}))"
echo "1..$((85 + ${extra_basic_tests:-0}))"
CHECKOUT_U_ARG=""
CHECKOUT_H_ARGS="-H"
@ -694,6 +694,35 @@ for v in bin link; do
done
echo "ok checkout union identical conflicts"
cd ${test_tmpdir}
rm files -rf && mkdir files
touch files/anemptyfile
touch files/anotheremptyfile
$CMD_PREFIX ostree --repo=repo commit --consume -b tree-with-empty-files --tree=dir=files
$CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} -z tree-with-empty-files tree-with-empty-files
if files_are_hardlinked tree-with-empty-files/an{,other}emptyfile; then
fatal "--force-copy-zerosized failed"
fi
rm tree-with-empty-files -rf
$CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} tree-with-empty-files tree-with-empty-files
assert_files_hardlinked tree-with-empty-files/an{,other}emptyfile
rm tree-with-empty-files -rf
echo "ok checkout --force-copy-zerosized"
# These should merge, they're identical
$CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} --union-identical -z tree-with-empty-files tree-with-empty-files
$CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} --union-identical -z tree-with-empty-files tree-with-empty-files
echo notempty > tree-with-empty-files/anemptyfile.new && mv tree-with-empty-files/anemptyfile{.new,}
$CMD_PREFIX ostree --repo=repo commit --consume -b tree-with-conflicting-empty-files --tree=dir=tree-with-empty-files
# Reset back to base
rm tree-with-empty-files -rf
$CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} --union-identical -z tree-with-empty-files tree-with-empty-files
if $CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} --union-identical -z tree-with-conflicting-empty-files tree-with-empty-files 2>err.txt; then
fatal "--union-identical --force-copy-zerosized unexpectedly succeeded with non-identical files"
fi
assert_file_has_content err.txt 'error:.*File exists'
echo "ok checkout --union-identical --force-copy-zerosized"
cd ${test_tmpdir}
rm files -rf && mkdir files
mkdir files/worldwritable-dir

View File

@ -430,6 +430,54 @@ test_devino_cache_xattrs (void)
g_assert_cmpint (stats.content_objects_written, ==, 1);
}
/* https://github.com/ostreedev/ostree/issues/1721
* We should be able to commit large metadata objects now.
*/
static void
test_big_metadata (void)
{
g_autoptr(GError) error = NULL;
gboolean ret = FALSE;
g_autoptr(GFile) repo_path = g_file_new_for_path ("repo");
/* init as bare-user-only so we run everywhere */
ret = ot_test_run_libtest ("setup_test_repository bare-user-only", &error);
g_assert_no_error (error);
g_assert (ret);
g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_path);
ret = ostree_repo_open (repo, NULL, &error);
g_assert_no_error (error);
g_assert (ret);
g_autoptr(GFile) object_to_commit = NULL;
ret = ostree_repo_read_commit (repo, "test2", &object_to_commit, NULL, NULL, &error);
g_assert_no_error (error);
g_assert (ret);
g_autoptr(OstreeMutableTree) mtree = ostree_mutable_tree_new ();
ret = ostree_repo_write_directory_to_mtree (repo, object_to_commit, mtree, NULL,
NULL, &error);
g_assert_no_error (error);
g_assert (ret);
const size_t len = 20 * 1024 * 1024;
g_assert_cmpint (len, >, OSTREE_MAX_METADATA_SIZE);
g_autofree char *large_buf = g_malloc (len);
memset (large_buf, 0x42, len);
g_autoptr(GVariantBuilder) builder =
g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
g_autofree char *commit_checksum = NULL;
g_variant_builder_add (builder, "{sv}", "large-value",
g_variant_new_fixed_array ((GVariantType*)"y",
large_buf, len, sizeof (char)));
ret = ostree_repo_write_commit (repo, NULL, NULL, NULL, g_variant_builder_end (builder),
OSTREE_REPO_FILE (object_to_commit), &commit_checksum, NULL, &error);
g_assert_no_error (error);
g_assert (ret);
}
int main (int argc, char **argv)
{
g_autoptr(GError) error = NULL;
@ -447,6 +495,7 @@ int main (int argc, char **argv)
g_test_add_func ("/xattrs-devino-cache", test_devino_cache_xattrs);
g_test_add_func ("/break-hardlink", test_break_hardlink);
g_test_add_func ("/remotename", test_validate_remotename);
g_test_add_func ("/big-metadata", test_big_metadata);
return g_test_run();
out:

View File

@ -192,6 +192,11 @@ done
${CMD_PREFIX} ostree --repo=repo refs -A > refs.txt
assert_file_has_content_literal refs.txt 'exampleos/x86_64/stable/server -> exampleos/x86_64/27/server'
# Test that we don't delete a ref having aliases
if ${CMD_PREFIX} ostree --repo=repo refs --delete exampleos/x86_64/27/server; then
assert_not_reached "refs --delete unexpectedly succeeded in deleting a ref containing alias!"
fi
${CMD_PREFIX} ostree --repo=repo summary -u
echo "ok ref symlink"

View File

@ -151,6 +151,52 @@ test_repo_equal (Fixture *fixture,
g_assert_false (ostree_repo_equal (closed_repo, closed_repo));
}
static void
test_repo_get_min_free_space (Fixture *fixture,
gconstpointer test_data)
{
g_autoptr (GKeyFile) config = NULL;
g_autoptr(GError) error = NULL;
guint64 bytes = 0;
typedef struct
{
const char *val;
gboolean should_succeed;
} min_free_space_value;
g_autoptr(OstreeRepo) repo = ostree_repo_create_at (fixture->tmpdir.fd, ".",
OSTREE_REPO_MODE_ARCHIVE,
NULL,
NULL, &error);
g_assert_no_error (error);
min_free_space_value values_to_test[] = {
{"500MB", TRUE },
{ "0MB", TRUE },
{ "17179869185GB", FALSE }, /* Overflow parameter: bytes > G_MAXUINT64 */
{ NULL, FALSE }
};
config = ostree_repo_copy_config (repo);
for (guint i = 0; values_to_test[i].val != NULL; i++)
{
g_key_file_remove_key (config, "core", "min-free-space-size", NULL);
g_key_file_set_string (config, "core", "min-free-space-size", values_to_test[i].val);
ostree_repo_write_config (repo, config, &error);
g_assert_no_error (error);
ostree_repo_reload_config (repo, NULL, &error);
g_assert_no_error (error);
ostree_repo_get_min_free_space_bytes (repo, &bytes, &error);
if (values_to_test[i].should_succeed)
g_assert_no_error (error);
else
continue;
}
}
int
main (int argc,
char **argv)
@ -164,6 +210,9 @@ main (int argc,
test_repo_hash_closed, teardown);
g_test_add ("/repo/equal", Fixture, NULL, setup,
test_repo_equal, teardown);
g_test_add ("/repo/get_min_free_space", Fixture, NULL, setup,
test_repo_get_min_free_space, teardown);
return g_test_run ();
}

View File

@ -54,7 +54,7 @@ echo 'ok documented symbols'
# ONLY update this checksum in release commits!
cat > released-sha256.txt <<EOF
a34e3681f1705ed3c6fcf25238e486365cb5b53ffde905ba28a2954ef6eb0269 ${released_syms}
ae2946567160d4a47c8a7d000b87306895ee72cdd339e157d21c839e4b2c003a ${released_syms}
EOF
sha256sum -c released-sha256.txt