]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:torture: Implement posix extension tests for libsmbclient
authorAndreas Schneider <asn@samba.org>
Thu, 27 Nov 2025 15:02:57 +0000 (16:02 +0100)
committerAndreas Schneider <asn@cryptomilk.org>
Tue, 9 Dec 2025 18:30:34 +0000 (18:30 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15960

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
selftest/knownfail.d/libsmbclient-posix [new file with mode: 0644]
source4/selftest/tests.py
source4/torture/libsmbclient/libsmbclient.c

diff --git a/selftest/knownfail.d/libsmbclient-posix b/selftest/knownfail.d/libsmbclient-posix
new file mode 100644 (file)
index 0000000..9986b91
--- /dev/null
@@ -0,0 +1,4 @@
+^samba4.libsmbclient.posix_extensions.NT1
+^samba4.libsmbclient.posix_extensions.SMB3
+^samba4.libsmbclient.posix_hardlinks.NT1
+^samba4.libsmbclient.posix_hardlinks.SMB3
index 0035c9509bbb5fe1c2755081b4c957f1ea43ff24..92cf9cdea0d114087e7b4377b68b99574a939fca 100755 (executable)
@@ -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',
index 72af8fc01c9189d79b168ceda216ea440ccb412b..7cb964bb6253344f5daab2a8e2acd6990434c1a8 100644 (file)
@@ -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");