From: Andreas Schneider Date: Thu, 27 Nov 2025 15:02:57 +0000 (+0100) Subject: s4:torture: Implement posix extension tests for libsmbclient X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e6e1cd753509698766de46df29c490fae5fcde9d;p=thirdparty%2Fsamba.git s4:torture: Implement posix extension tests for libsmbclient BUG: https://bugzilla.samba.org/show_bug.cgi?id=15960 Signed-off-by: Andreas Schneider Reviewed-by: Ralph Boehme --- diff --git a/selftest/knownfail.d/libsmbclient-posix b/selftest/knownfail.d/libsmbclient-posix new file mode 100644 index 00000000000..9986b917b8c --- /dev/null +++ b/selftest/knownfail.d/libsmbclient-posix @@ -0,0 +1,4 @@ +^samba4.libsmbclient.posix_extensions.NT1 +^samba4.libsmbclient.posix_extensions.SMB3 +^samba4.libsmbclient.posix_hardlinks.NT1 +^samba4.libsmbclient.posix_hardlinks.SMB3 diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 0035c9509bb..92cf9cdea0d 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -449,6 +449,8 @@ for t in libsmbclient: url = "smb://$USERNAME:$PASSWORD@$SERVER" if t == "libsmbclient.utimes": url += "/utimes.txt" + if t == "libsmbclient.posix_extensions" or t == "libsmbclient.posix_hardlinks": + url = "smb://$USERNAME:$PASSWORD@$SERVER/smb3_posix_share" libsmbclient_testargs = [ '//$SERVER/tmp', diff --git a/source4/torture/libsmbclient/libsmbclient.c b/source4/torture/libsmbclient/libsmbclient.c index 72af8fc01c9..7cb964bb625 100644 --- a/source4/torture/libsmbclient/libsmbclient.c +++ b/source4/torture/libsmbclient/libsmbclient.c @@ -1578,6 +1578,208 @@ static bool torture_libsmbclient_getxattr(struct torture_context *tctx) return ok; } +static bool torture_libsmbclient_init_posix_context(struct torture_context *tctx, + SMBCCTX **ctx_p) +{ + SMBCCTX *ctx = NULL; + SMBCCTX *p = NULL; + bool ok = true; + + ctx = smbc_new_context(); + torture_assert_not_null_goto( + tctx, ctx, ok, out, "Failed to create new context"); + + torture_comment(tctx, "Enabling POSIX extensions\n"); + smbc_setOptionPosixExtensions(ctx, true); + + p = smbc_init_context(ctx); + torture_assert_not_null_goto(tctx, + p, + ok, + out, + "Failed to initialize context"); + + smbc_setFunctionAuthData(ctx, auth_callback); + smbc_set_context(ctx); + + *ctx_p = ctx; + +out: + if (!ok) { + smbc_free_context(ctx, true); + } + + return ok; +} + +static bool torture_libsmbclient_posix_extensions(struct torture_context *tctx) +{ + const char *smburl = torture_setting_string(tctx, "smburl", NULL); + int fhandle = -1; + SMBCCTX *ctx = NULL; + char *posix_name = NULL; + char buf[2] = {'\0'}; + bool ok = false; + int ret = -1; + + if (smburl == NULL) { + torture_fail(tctx, + "option --option=torture:smburl=" + "smb://user:password@server missing\n"); + } + + torture_assert_goto(tctx, + torture_libsmbclient_init_posix_context(tctx, &ctx), + ok, + done, + "Failed to init POSIX context"); + + posix_name = talloc_asprintf(tctx, + "%s/posix_test_original.txt", + smburl); + torture_assert_not_null_goto(tctx, + posix_name, + ok, + done, + "talloc_asprintf failed\n"); + + /* Open the test file */ + fhandle = smbc_open(posix_name, O_RDONLY, 0); + torture_assert_goto(tctx, + fhandle >= 0, + ok, + done, + talloc_asprintf(tctx, + "failed to open file '%s': %s", + posix_name, + strerror(errno))); + + /* + * Check if we got POSIX extensions by reading the + * "posix.attr.enabled" extended attribute. + * This should return "1" if POSIX extensions are active. + */ + torture_comment(tctx, "Checking for POSIX extensions\n"); + ret = smbc_fgetxattr(fhandle, "posix.attr.enabled", buf, sizeof(buf)); + + torture_assert_int_equal_goto( + tctx, + ret, + 1, + ok, + done, + "smbc_fgetxattr(posix.attr.enabled) failed"); + + torture_assert_str_equal_goto( + tctx, buf, "1", ok, done, "POSIX extensions not enabled."); + torture_comment(tctx, "POSIX extensions are enabled!\n"); + + ok = true; + +done: + if (fhandle >= 0) { + smbc_close(fhandle); + } + if (ctx != NULL) { + smbc_free_context(ctx, 1); + } + + return ok; +} + +static bool torture_libsmbclient_posix_hardlinks(struct torture_context *tctx) +{ + const char *smburl = torture_setting_string(tctx, "smburl", NULL); + int fhandle = -1; + SMBCCTX *ctx = NULL; + char *posix_name = NULL; + char buf[sizeof(struct stat) + 4]; /* +4 bytes for DOS attributes */ + struct stat st_posix; + bool ok = false; + int ret = -1; + + if (smburl == NULL) { + torture_fail(tctx, + "option --option=torture:smburl=" + "smb://user:password@server missing\n"); + } + + torture_assert_goto(tctx, + torture_libsmbclient_init_posix_context(tctx, &ctx), + ok, + done, + "Failed to init POSIX context"); + + posix_name = talloc_asprintf(tctx, + "%s/posix_test_original.txt", + smburl); + torture_assert_not_null_goto(tctx, + posix_name, + ok, + done, + "talloc_asprintf failed\n"); + + /* Open the file with hardlinks */ + fhandle = smbc_open(posix_name, O_RDONLY, 0); + torture_assert_goto(tctx, + fhandle >= 0, + ok, + done, + talloc_asprintf(tctx, + "failed to open file '%s': %s", + posix_name, + strerror(errno))); + + /* + * Get POSIX stat information including hardlink count + */ + torture_comment(tctx, "Getting POSIX stat info for hardlink test\n"); + ret = smbc_fgetxattr(fhandle, + "smb311_posix.statinfo", + buf, + sizeof(buf)); + + torture_assert_int_equal_goto( + tctx, + ret, + sizeof(struct stat), + ok, + done, + talloc_asprintf(tctx, + "smbc_fgetxattr(smb311_posix.statinfo) " + "returned %d, expected %zu", + ret, + sizeof(struct stat))); + + memcpy(&st_posix, buf, sizeof(struct stat)); + + torture_comment(tctx, + "File has %lu hardlinks\n", + (unsigned long)st_posix.st_nlink); + + torture_assert_int_equal_goto( + tctx, + st_posix.st_nlink, + 3, + ok, + done, + talloc_asprintf(tctx, + "Expected 3 hardlinks, got %lu", + (unsigned long)st_posix.st_nlink)); + + ok = true; + +done: + if (fhandle >= 0) { + smbc_close(fhandle); + } + if (ctx != NULL) { + smbc_free_context(ctx, 1); + } + + return ok; +} + NTSTATUS torture_libsmbclient_init(TALLOC_CTX *ctx) { struct torture_suite *suite; @@ -1608,6 +1810,10 @@ NTSTATUS torture_libsmbclient_init(TALLOC_CTX *ctx) torture_libsmbclient_getatr); torture_suite_add_simple_test(suite, "getxattr", torture_libsmbclient_getxattr); + torture_suite_add_simple_test(suite, "posix_extensions", + torture_libsmbclient_posix_extensions); + torture_suite_add_simple_test(suite, "posix_hardlinks", + torture_libsmbclient_posix_hardlinks); suite->description = talloc_strdup(suite, "libsmbclient interface tests");