diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 3f48ef3a..65b9e7fd 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -356,6 +356,7 @@ ostree_repo_write_metadata_async ostree_repo_write_metadata_finish ostree_repo_write_content ostree_repo_write_regfile_inline +ostree_repo_write_symlink ostree_repo_write_metadata_trusted ostree_repo_write_metadata_stream_trusted ostree_repo_write_content_trusted diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index c4a70938..e218ddda 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -25,6 +25,7 @@ LIBOSTREE_2021.2 { global: ostree_repo_write_regfile_inline; + ostree_repo_write_symlink; } LIBOSTREE_2021.1; /* Stub section for the stable release *after* this development one; don't diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 409738ad..ae93eedb 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2814,6 +2814,47 @@ ostree_repo_write_regfile_inline (OstreeRepo *self, return ostree_checksum_from_bytes (csum); } +/** + * ostree_repo_write_symlink: + * @self: repo + * @expected_checksum: (allow-none): The expected checksum + * @uid: User id + * @gid: Group id + * @xattrs: (allow-none): Extended attributes, GVariant of type (ayay) + * @symlink_target: Target of the symbolic link + * @cancellable: Cancellable + * @error: Error + * + * Synchronously create a symlink object. + * + * Unlike `ostree_repo_write_content()`, if @expected_checksum is provided, + * this function will not check for the presence of the object beforehand. + * + * Returns: (transfer full): Checksum (as a hex string) of the committed file + * Since: 2021.2 + */ +char * +ostree_repo_write_symlink (OstreeRepo *self, + const char *expected_checksum, + guint32 uid, + guint32 gid, + GVariant *xattrs, + const char *symlink_target, + GCancellable *cancellable, + GError **error) +{ + g_assert (symlink_target != NULL); + + g_autoptr(GFileInfo) finfo = _ostree_mode_uidgid_to_gfileinfo (S_IFLNK | 0777, uid, gid); + g_file_info_set_attribute_byte_string (finfo, "standard::symlink-target", symlink_target); + g_autofree guint8* csum = NULL; + if (!write_content_object (self, expected_checksum, + NULL, finfo, xattrs, &csum, + cancellable, error)) + return NULL; + return ostree_checksum_from_bytes (csum); +} + typedef struct { OstreeRepo *repo; char *expected_checksum; diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index cd50fc43..7e08361b 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -435,6 +435,16 @@ char * ostree_repo_write_regfile_inline (OstreeRepo *self, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +char * ostree_repo_write_symlink (OstreeRepo *self, + const char *expected_checksum, + guint32 uid, + guint32 gid, + GVariant *xattrs, + const char *symlink_target, + GCancellable *cancellable, + GError **error); + _OSTREE_PUBLIC gboolean ostree_repo_write_metadata_trusted (OstreeRepo *self, OstreeObjectType objtype, diff --git a/tests/test-core.js b/tests/test-core.js index 8f460a5f..5f3e9fe3 100755 --- a/tests/test-core.js +++ b/tests/test-core.js @@ -56,6 +56,7 @@ let inline_checksum = repo.write_regfile_inline(null, 0, 0, regfile_mode, null, assertEquals(inline_checksum, "8aaa9dc13a0c5839fe4a277756798c609c53fac6fa2290314ecfef9041065873"); let written = false; try { + // Changed an a to b from above to make the checksum not match repo.write_regfile_inline("8baa9dc13a0c5839fe4a277756798c609c53fac6fa2290314ecfef9041065873", 0, 0, regfile_mode, null, inline_content, null); written = true; } catch (e) { diff --git a/tests/test-repo.c b/tests/test-repo.c index ad81a7d6..35e929f9 100644 --- a/tests/test-repo.c +++ b/tests/test-repo.c @@ -236,6 +236,18 @@ test_write_regfile_api (Fixture *fixture, g_assert_no_error (error); g_assert_cmpstr (checksum, ==, "4f600d252338f93279c51c964915cb2c26f0d09082164c54890d1a3c78cdeb1e"); g_clear_pointer (&checksum, g_free); + + // Test symlinks + g_clear_pointer (&xattrs, g_variant_unref); + g_variant_builder_init (&xattrs_builder, (GVariantType*)"a(ayay)"); + g_variant_builder_add (&xattrs_builder, "(^ay^ay)", "security.selinux", "system_u:object_r:bin_t:s0"); + g_clear_pointer (&xattrs, g_variant_unref); + xattrs = g_variant_ref_sink (g_variant_builder_end (&xattrs_builder)); + + g_clear_pointer (&checksum, g_free); + checksum = ostree_repo_write_symlink (repo, NULL, 0, 0, xattrs, "bash", NULL, &error); + g_assert_no_error (error); + g_assert_cmpstr (checksum, ==, "23a2e97d21d960ac7a4e39a8721b1baff7b213e00e5e5641334f50506012fcff"); } int