summaryrefslogtreecommitdiff
path: root/tests/test-basic-c.c
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2017-12-14 11:10:35 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2017-12-14 21:56:26 +0000
commit4a2e08148de1ada60ba854b21489159229ed08e3 (patch)
treee82cc04070c3b8f4e6ba7004eef6d08a9dc77d4d /tests/test-basic-c.c
parentd340fe406079c4b3c2b62af2a1c10cd9afd44b09 (diff)
downloadostree-4a2e08148de1ada60ba854b21489159229ed08e3.tar.gz
lib/core: Add a "break hardlink" API
This imports the code from rpm-ostree: https://github.com/projectatomic/rpm-ostree/blob/9ff9f6c997d914cb7d97d6b59d8045ba64a1882c/src/libpriv/rpmostree-util.c#L742 I plan to use this for rofiles-fuse to implement copyup: https://github.com/ostreedev/ostree/issues/1377 But it's just obviously generally useful for projects using libostree I think. Closes: #1378 Approved by: jlebon
Diffstat (limited to 'tests/test-basic-c.c')
-rw-r--r--tests/test-basic-c.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/tests/test-basic-c.c b/tests/test-basic-c.c
index f7e85438..4ca379e8 100644
--- a/tests/test-basic-c.c
+++ b/tests/test-basic-c.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <gio/gio.h>
#include <string.h>
+#include <err.h>
#include "libglnx.h"
#include "libostreetest.h"
@@ -236,6 +237,72 @@ test_object_writes (gconstpointer data)
}
}
+static gboolean
+impl_test_break_hardlink (int tmp_dfd,
+ const char *path,
+ GError **error)
+{
+ const char *linkedpath = glnx_strjoina (path, ".link");
+ struct stat orig_stbuf;
+ if (!glnx_fstatat (tmp_dfd, path, &orig_stbuf, AT_SYMLINK_NOFOLLOW, error))
+ return FALSE;
+
+ /* Calling ostree_break_hardlink() should be a noop */
+ struct stat stbuf;
+ if (!ostree_break_hardlink (tmp_dfd, path, TRUE, NULL, error))
+ return FALSE;
+ if (!glnx_fstatat (tmp_dfd, path, &stbuf, AT_SYMLINK_NOFOLLOW, error))
+ return FALSE;
+
+ g_assert_cmpint (orig_stbuf.st_dev, ==, stbuf.st_dev);
+ g_assert_cmpint (orig_stbuf.st_ino, ==, stbuf.st_ino);
+
+ if (linkat (tmp_dfd, path, tmp_dfd, linkedpath, 0) < 0)
+ return glnx_throw_errno_prefix (error, "linkat");
+
+ if (!ostree_break_hardlink (tmp_dfd, path, TRUE, NULL, error))
+ return FALSE;
+ if (!glnx_fstatat (tmp_dfd, path, &stbuf, AT_SYMLINK_NOFOLLOW, error))
+ return FALSE;
+ /* This file should be different */
+ g_assert_cmpint (orig_stbuf.st_dev, ==, stbuf.st_dev);
+ g_assert_cmpint (orig_stbuf.st_ino, !=, stbuf.st_ino);
+ /* But this one is still the same */
+ if (!glnx_fstatat (tmp_dfd, linkedpath, &stbuf, AT_SYMLINK_NOFOLLOW, error))
+ return FALSE;
+ g_assert_cmpint (orig_stbuf.st_dev, ==, stbuf.st_dev);
+ g_assert_cmpint (orig_stbuf.st_ino, ==, stbuf.st_ino);
+
+ (void) unlinkat (tmp_dfd, path, 0);
+ (void) unlinkat (tmp_dfd, linkedpath, 0);
+
+ return TRUE;
+}
+
+static void
+test_break_hardlink (void)
+{
+ int tmp_dfd = AT_FDCWD;
+ g_autoptr(GError) error = NULL;
+
+ /* Regular file */
+ const char hello_hardlinked_content[] = "hello hardlinked content";
+ glnx_file_replace_contents_at (tmp_dfd, "test-hardlink",
+ (guint8*)hello_hardlinked_content,
+ strlen (hello_hardlinked_content),
+ GLNX_FILE_REPLACE_NODATASYNC,
+ NULL, &error);
+ g_assert_no_error (error);
+ (void)impl_test_break_hardlink (tmp_dfd, "test-hardlink", &error);
+ g_assert_no_error (error);
+
+ /* Symlink */
+ if (symlinkat ("some-path", tmp_dfd, "test-symhardlink") < 0)
+ err (1, "symlinkat");
+ (void)impl_test_break_hardlink (tmp_dfd, "test-symhardlink", &error);
+ g_assert_no_error (error);
+}
+
static GVariant*
xattr_cb (OstreeRepo *repo,
const char *path,
@@ -376,6 +443,7 @@ int main (int argc, char **argv)
g_test_add_data_func ("/raw-file-to-archive-stream", repo, test_raw_file_to_archive_stream);
g_test_add_data_func ("/objectwrites", repo, test_object_writes);
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);
return g_test_run();