The branch, master has been updated
via 2493bfa84e4 s3:include: Fix the smbc_fgetxattr() documentation in
libsmbclient
via 1b5e40ef37e s3:libsmb: Call the correct function in smbc_fgetxattr()
via 8c276ff55ef libsmbclient: Fix negotiating posix_extensions
via e6e1cd75350 s4:torture: Implement posix extension tests for
libsmbclient
via 3a5826d2fac selftest: Add some hardlinks for testing SMB3 posix
extensions
from 249e77e24d8 bootstrap: Update Fedora to version 43
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 2493bfa84e48badb9e7e8460e16aea68f90f431b
Author: Andreas Schneider <[email protected]>
Date: Thu Nov 27 17:07:02 2025 +0100
s3:include: Fix the smbc_fgetxattr() documentation in libsmbclient
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15960
Signed-off-by: Andreas Schneider <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
Autobuild-User(master): Andreas Schneider <[email protected]>
Autobuild-Date(master): Tue Dec 9 19:33:22 UTC 2025 on atb-devel-224
commit 1b5e40ef37eacaf2598401b43c1e9944e88a2308
Author: Andreas Schneider <[email protected]>
Date: Tue Nov 25 17:21:49 2025 +0100
s3:libsmb: Call the correct function in smbc_fgetxattr()
Looks like nobody ever tested this.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15960
Signed-off-by: Andreas Schneider <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 8c276ff55efd3577e2a141613190231eefb8063f
Author: Andreas Schneider <[email protected]>
Date: Tue Nov 25 19:06:48 2025 +0100
libsmbclient: Fix negotiating posix_extensions
Without this, smbc_setOptionPosixExtensions() does nothing.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15960
Signed-off-by: Andreas Schneider <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit e6e1cd753509698766de46df29c490fae5fcde9d
Author: Andreas Schneider <[email protected]>
Date: Thu Nov 27 16:02:57 2025 +0100
s4:torture: Implement posix extension tests for libsmbclient
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15960
Signed-off-by: Andreas Schneider <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 3a5826d2facf140e610ca08cc80340c7aa5cf96a
Author: Andreas Schneider <[email protected]>
Date: Thu Nov 27 16:33:28 2025 +0100
selftest: Add some hardlinks for testing SMB3 posix extensions
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15960
Signed-off-by: Andreas Schneider <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
-----------------------------------------------------------------------
Summary of changes:
selftest/target/Samba3.pm | 8 ++
source3/include/libsmbclient.h | 28 +++-
source3/libsmb/libsmb_compat.c | 5 +-
source3/libsmb/libsmb_server.c | 57 +++-----
source4/selftest/tests.py | 2 +
source4/torture/libsmbclient/libsmbclient.c | 206 ++++++++++++++++++++++++++++
6 files changed, 266 insertions(+), 40 deletions(-)
Changeset truncated at 500 lines:
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index ee1d8802223..dc6f7314a5d 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -2881,6 +2881,14 @@ sub provision($$)
##
symlink "$widelinks_shrdir", "$widelinks_shrdir/dot";
+ ##
+ ## Create test file with hardlinks for posix extensions testing with
+ ## [smb3_posix_share]
+ ##
+ create_file_chmod("$shrdir/posix_test_original.txt", 0644) or return
undef;
+ link "$shrdir/posix_test_original.txt",
"$shrdir/posix_test_hardlink1.txt";
+ link "$shrdir/posix_test_original.txt",
"$shrdir/posix_test_hardlink2.txt";
+
my $conffile="$libdir/server.conf";
my $dfqconffile="$libdir/dfq.conf";
my $errorinjectconf="$libdir/error_inject.conf";
diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h
index 948eba3361a..e3a2094754e 100644
--- a/source3/include/libsmbclient.h
+++ b/source3/include/libsmbclient.h
@@ -2477,6 +2477,31 @@ int smbc_lgetxattr(const char *url,
* to names. Without the plus sign, SIDs are not mapped;
* rather they are simply converted to a string format.
*
+ * When POSIX extensions are enabled (via
+ * smbc_setOptionPosixExtensions()), the following additional
+ * attribute names are available:
+ *
+ * posix.attr.enabled
+ * Returns "1" if POSIX extensions are active on the
+ * server connection, "0" otherwise. The value buffer
+ * must be at least 2 bytes to include the null
+ * terminator. The returned size is 1 (excluding the
+ * null terminator).
+ * This is only a check on internal structures, it
+ * doesn't produce any network traffic.
+ *
+ * smb311_posix.statinfo
+ * Returns POSIX stat information via a network call to
+ * the server. The value buffer must be at least
+ * sizeof(struct stat) + 4 bytes. The buffer contains a
+ * struct stat followed by 4 bytes of DOS attributes.
+ * The returned size is sizeof(struct stat), which
+ * should be used as the offset to read the DOS
+ * attributes from the buffer. This provides e.g the
+ * correct uid/gid on the server and hardlink counts
+ * (st_nlink) and other POSIX metadata not available
+ * through standard stat calls.
+ *
* @param value A pointer to a buffer in which the value of the specified
* attribute will be placed (unless size is zero).
*
@@ -2485,7 +2510,8 @@ int smbc_lgetxattr(const char *url,
* required to hold the attribute value will be returned,
* but nothing will be placed into the value buffer.
*
- * @return 0 on success, < 0 on error with errno set:
+ * @return On success, the number of bytes of the extended attribute
+ * returned. On error, -1 is returned with errno set:
* - EINVAL The client library is not properly initialized
* or one of the parameters is not of a correct
* form
diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c
index 465bb3c70ee..2a064ec0938 100644
--- a/source3/libsmb/libsmb_compat.c
+++ b/source3/libsmb/libsmb_compat.c
@@ -482,9 +482,8 @@ smbc_fgetxattr(int fd,
errno = EBADF;
return -1;
}
- return smbc_getFunctionGetxattr(statcont)(statcont,
- file->fname, name,
- value, size);
+ return smbc_getFunctionFGetxattr(statcont)
+ (statcont, file, name, value, size);
}
int
diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index f9b52e1f05a..7b1def05f0b 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -547,6 +547,10 @@ SMBC_server_internal(TALLOC_CTX *ctx,
signing_state = SMB_SIGNING_REQUIRED;
}
+ if (context->internal->posix_extensions) {
+ flags |= CLI_FULL_CONNECTION_REQUEST_POSIX;
+ }
+
if (nts.num_transports != 0 && ots.num_transports != 0) {
if (share == NULL || *share == '\0' || is_ipc) {
/*
@@ -554,15 +558,15 @@ SMBC_server_internal(TALLOC_CTX *ctx,
*/
ts = &ots;
- status = cli_connect_nb(NULL,
- server_n,
- NULL,
- &nts,
- 0x20,
- smbc_getNetbiosName(context),
- signing_state,
- flags,
- &c);
+ status = cli_start_connection(
+ context->internal->mem_ctx,
+ &c,
+ smbc_getNetbiosName(context),
+ server_n,
+ NULL, /* dest_ss */
+ &nts, /* transports */
+ signing_state,
+ flags);
}
}
@@ -570,15 +574,14 @@ SMBC_server_internal(TALLOC_CTX *ctx,
/*
* No IPC$ or 139 did not work
*/
- status = cli_connect_nb(NULL,
- server_n,
- NULL,
- ts,
- 0x20,
- smbc_getNetbiosName(context),
- signing_state,
- flags,
- &c);
+ status = cli_start_connection(context->internal->mem_ctx,
+ &c,
+ smbc_getNetbiosName(context),
+ server_n,
+ NULL, /* dest_ss */
+ ts, /* transports */
+ signing_state,
+ flags);
}
if (!NT_STATUS_IS_OK(status)) {
@@ -592,24 +595,6 @@ SMBC_server_internal(TALLOC_CTX *ctx,
cli_set_timeout(c, smbc_getTimeout(context));
- status = smbXcli_negprot(c->conn,
- c->timeout,
- lp_client_min_protocol(),
- lp_client_max_protocol(),
- NULL,
- NULL,
- NULL);
- if (!NT_STATUS_IS_OK(status)) {
- cli_shutdown(c);
- errno = map_errno_from_nt_status(status);
- return NULL;
- }
-
- if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
- /* Ensure we ask for some initial credits. */
- smb2cli_conn_set_max_credits(c->conn, DEFAULT_SMB2_MAX_CREDITS);
- }
-
username_used = *pp_username;
password_used = *pp_password;
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");
--
Samba Shared Repository