From: Colin Walters Date: Wed, 13 Mar 2024 16:50:28 +0000 (-0400) Subject: checkout: Always replace existing content in overlay mode X-Git-Tag: archive/raspbian/2024.8-1+rpi1^2~7^2~3^2~1^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=bb6dfd3ab0bbd87497e58bc0dd0ec65c061c9a12;p=ostree.git checkout: Always replace existing content in overlay mode The combination of the "honor whiteout" and "union" flags are intended to basically be "merge trees like overlayfs does". But we were missing this case in order to support e.g. replacing a symlink with a directory. --- diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index f5065455..65060444 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -1062,6 +1062,22 @@ checkout_tree_at_recurse (OstreeRepo *self, OstreeRepoCheckoutAtOptions *options if (!glnx_shutil_rm_rf_at (destination_parent_fd, destination_name, cancellable, error)) return FALSE; } + else if (options->process_whiteouts + && options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES) + { + /* In this mode, we're flattening in a manner similar to overlayfs, so ensure + * any non-directory content there is gone. / + */ + struct stat stbuf; + if (!glnx_fstatat_allow_noent (destination_parent_fd, destination_name, &stbuf, + AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + if (errno == 0 && !S_ISDIR (stbuf.st_mode)) + { + 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 diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 7905e6ee..c8f853f8 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -1159,6 +1159,18 @@ if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper && touch overlay/baz/an assert_has_file overlay-co/baz test -L overlay-co/anewdir + rm overlay-co overlay -rf + mkdir -p overlay/somelink overlay/yet/ovlnewdir + echo ovlnewf > overlay/yet/ovlnewdir/ovlnewf + $OSTREE --repo=repo commit ${COMMIT_ARGS} -b overlay-symlink-convert --tree=dir=overlay + for branch in test2 overlay-symlink-convert; do + $OSTREE --repo=repo checkout --union --whiteouts ${branch} overlay-co + done + test -d overlay-co/somelink || fatal "should replace symlink with dir" + assert_has_dir overlay-co/yet/another + assert_has_dir overlay-co/yet/ovlnewdir + assert_file_has_content overlay-co/yet/ovlnewdir/ovlnewf ovlnewf + rm overlay-co overlay -rf echo "ok whiteouts enabled" # Now double check whiteouts are not processed without --whiteouts