}
static int
-verify_write_or_copyup (const char *path, const struct stat *stbuf)
+verify_write_or_copyup (const char *path, const struct stat *stbuf,
+ gboolean *out_did_copyup)
{
struct stat stbuf_local;
+ if (out_did_copyup)
+ *out_did_copyup = FALSE;
+
/* If a stbuf wasn't provided, gather it now */
if (!stbuf)
{
g_autoptr(GError) tmp_error = NULL;
if (!ostree_break_hardlink (basefd, path, FALSE, NULL, &tmp_error))
return -gioerror_to_errno ((GIOErrorEnum)tmp_error->code);
+ if (out_did_copyup)
+ *out_did_copyup = TRUE;
}
else
return -EROFS;
*/
#define PATH_WRITE_ENTRYPOINT(path) do { \
path = ENSURE_RELPATH (path); \
- int r = verify_write_or_copyup (path, NULL); \
+ int r = verify_write_or_copyup (path, NULL, NULL); \
if (r != 0) \
return r; \
} while (0)
return -errno;
}
- int r = verify_write_or_copyup (path, &stbuf);
+ gboolean did_copyup;
+ int r = verify_write_or_copyup (path, &stbuf, &did_copyup);
if (r != 0)
{
(void) close (fd);
}
/* In the copyup case, we need to re-open */
- if (opt_copyup)
+ if (did_copyup)
{
(void) close (fd);
/* Note that unlike the initial open, we will pass through
# And now with --copyup enabled
-fusermount -u ${test_tmpdir}/mnt
-assert_not_has_file mnt/firstfile
-rofiles-fuse --copyup checkout-test2 mnt
+copyup_reset() {
+ cd ${test_tmpdir}
+ fusermount -u mnt
+ rm checkout-test2 -rf
+ $OSTREE checkout -H test2 checkout-test2
+ rofiles-fuse --copyup checkout-test2 mnt
+}
+
+assert_test_file() {
+ t=$1
+ f=$2
+ if ! test ${t} "${f}"; then
+ ls -al "${f}"
+ fatal "Failed test ${t} ${f}"
+ fi
+}
+
+copyup_reset
assert_file_has_content mnt/firstfile first
echo "ok copyup mount"
+# Test O_TRUNC directly
firstfile_orig_inode=$(stat -c %i checkout-test2/firstfile)
-for path in firstfile{,-link}; do
- echo truncating > mnt/${path}
- assert_file_has_content mnt/${path} truncating
- assert_not_file_has_content mnt/${path} first
-done
+echo -n truncating > mnt/firstfile
+assert_streq "$(cat mnt/firstfile)" truncating
+firstfile_new_inode=$(stat -c %i checkout-test2/firstfile)
+assert_not_streq "${firstfile_orig_inode}" "${firstfile_new_inode}"
+assert_test_file -f checkout-test2/firstfile
+
+copyup_reset
+firstfile_link_orig_inode=$(stat -c %i checkout-test2/firstfile-link)
+firstfile_orig_inode=$(stat -c %i checkout-test2/firstfile)
+# Now write via the symlink
+echo -n truncating > mnt/firstfile-link
+assert_streq "$(cat mnt/firstfile)" truncating
firstfile_new_inode=$(stat -c %i checkout-test2/firstfile)
+firstfile_link_new_inode=$(stat -c %i checkout-test2/firstfile-link)
assert_not_streq "${firstfile_orig_inode}" "${firstfile_new_inode}"
+assert_streq "${firstfile_link_orig_inode}" "${firstfile_link_new_inode}"
+assert_test_file -f checkout-test2/firstfile
+# Verify we didn't replace the link with a regfile somehow
+assert_test_file -L checkout-test2/firstfile-link
+
+# These both end up creating new files; in the sed case we'll then do a rename()
+copyup_reset
+echo "hello new file" > mnt/a-new-non-copyup-file
+assert_file_has_content_literal mnt/a-new-non-copyup-file "hello new file"
+sed -i -e s,first,second, mnt/firstfile
+assert_file_has_content_literal mnt/firstfile "second"
echo "ok copyup"