Skip to content

Commit

Permalink
checkout: honor opaque checkouts
Browse files Browse the repository at this point in the history
Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Aug 7, 2018
1 parent 521e0ec commit 5bedcad
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
25 changes: 25 additions & 0 deletions src/libostree/ostree-repo-checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "ostree-repo-private.h"

#define WHITEOUT_PREFIX ".wh."
#define OPAQUE_WHITEOUT_NAME ".wh..wh..opq"

/* Per-checkout call state/caching */
typedef struct {
Expand Down Expand Up @@ -845,6 +846,7 @@ checkout_tree_at_recurse (OstreeRepo *self,
GError **error)
{
gboolean did_exist = FALSE;
gboolean is_opaque_whiteout = FALSE;
const gboolean sepolicy_enabled = options->sepolicy && !self->disable_xattrs;
g_autoptr(GVariant) dirtree = NULL;
g_autoptr(GVariant) dirmeta = NULL;
Expand Down Expand Up @@ -878,6 +880,22 @@ checkout_tree_at_recurse (OstreeRepo *self,
return TRUE; /* Note early return */
}

if (options->process_whiteouts)
{
g_autoptr(GVariant) dir_file_contents = g_variant_get_child_value (dirtree, 0);
GVariantIter viter;
const char *fname;
g_autoptr(GVariant) contents_csum_v = NULL;
g_variant_iter_init (&viter, dir_file_contents);
while (g_variant_iter_loop (&viter, "(&s@ay)", &fname, &contents_csum_v))
{
is_opaque_whiteout = (g_str_equal (fname, OPAQUE_WHITEOUT_NAME));
if (is_opaque_whiteout)
break;
}
contents_csum_v = NULL; /* iter_loop freed it */
}

/* First, make the directory. Push a new scope in case we end up using
* setfscreatecon().
*/
Expand All @@ -897,6 +915,13 @@ checkout_tree_at_recurse (OstreeRepo *self,
return FALSE;
}

/* If it is an opaque whiteout, ensure the destination is empty first. */
if (is_opaque_whiteout)
{
if (!glnx_shutil_rm_rf_at (destination_parent_fd, destination_name, cancellable, error))
return FALSE;
}

/* Create initially with mode 0700, then chown/chmod only when we're
* done. This avoids anyone else being able to operate on partially
* constructed dirs.
Expand Down
3 changes: 2 additions & 1 deletion tests/basic-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ echo "ok test error pre commit/bootid"
# Whiteouts
cd ${test_tmpdir}
mkdir -p overlay/baz/
if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper; then
if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper && touch overlay/baz/another/.wh..wh..opq; then
touch overlay/anewfile
mkdir overlay/anewdir/
touch overlay/anewdir/blah
Expand All @@ -1021,6 +1021,7 @@ if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper; then
assert_not_has_dir overlay-co/deeper
assert_has_file overlay-co/anewdir/blah
assert_has_file overlay-co/anewfile
assert_not_has_file overlay-co/baz/another/y

# And test replacing a directory wholesale with a symlink as well as a regular file
mkdir overlay
Expand Down

0 comments on commit 5bedcad

Please sign in to comment.