[SCM] Samba Shared Repository - branch master updated
Stefan Metzmacher
metze at samba.org
Wed Aug 21 09:18:02 UTC 2024
The branch, master has been updated
via 3790d0d3b98 WHATSNEW: add 'vfs mkdir use tmp name' option
via 1bacaae5261 s3:smbd: let mkdir_internal() try VFS_RENAME_HOW_NO_REPLACE first
via fe8b4617ddc s3:vfs_default: implement VFS_RENAME_HOW_NO_REPLACE in vfswrap_renameat()
via adc8dea944b s3:vfs: add VFS_RENAME_HOW_NO_REPLACE
via 5b305d1fbb2 s3:vfs: add vfs_rename_how to SMB_VFS_RENAMEAT()
via f6550e804ea lib/replace: add renameat2() replacement
via 7baeeece2dd s3:smbd: let mkdir_internal() work more atomically using a temporary name
via 460e280d3af docs-xml: add 'vfs mkdir use tmp name' option
via f8be83a0a33 s3:smbd: improve DEBUG messages in mkdir_internal()
via 5d077cd4421 s3:smbd: let mkdir_internal() use a talloc_stackframe()
via 23f85e60ec9 s3:smbd: call apply_new_nt_acl() already in mkdir_internals()
via 75fe450f98c s3:smbd: split out apply_new_nt_acl() helper
via 30ddbe4611c lib/util: let server_id_str_buf_unique() use server_id_buf
via 20431cc6227 lib/util: split out server_id_from_string_ex allow the unique delimiter to be passed in
via 86952314036 lib/util: add server_id_str_buf_unique_ex() and allow the delimiter to be passed in
via c815128caa7 lib/util: let server_id_str_buf() use PRIu32 and PRIu64
via 87aa3a46a3d lib/util: add a comment to struct server_id_buf
via f9d7a930f00 s4:torture/smb2: add smb2.create.mkdir-visible
from ffc75c569c6 lib/param: Don't treat a missing include file as an error in handle_include().
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 3790d0d3b989d7edbe34888bb068f54f0cb1282d
Author: Stefan Metzmacher <metze at samba.org>
Date: Mon Aug 12 14:41:47 2024 +0200
WHATSNEW: add 'vfs mkdir use tmp name' option
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
Autobuild-Date(master): Wed Aug 21 09:18:00 UTC 2024 on atb-devel-224
commit 1bacaae5261b157f0dc4efb68fdc82d4cf387eb9
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Aug 7 17:01:53 2024 +0200
s3:smbd: let mkdir_internal() try VFS_RENAME_HOW_NO_REPLACE first
With renameat2(RENAME_NOREPLACE) being available
it's even better, as we don't even have the short
window where the incomplete directory is visible
to others.
The flow will be this:
tmp_name = ".::TMPNAME:D:$PID:client_name"
mkdirat(tmp_name, mode=client_mode);
prepare_acls(tmp_name);
renameat2(tmp_name, client_name, NOREPLACE);
if (EEXIST) {
unlinkat(tmp_name);
return EEXIST;
}
if (EINVAL) {
/* fallback if NOREPLACE is not supported */
mkdirat(client_name, mode=0);
if (EEXIST) {
unlinkat(tmp_name);
return EEXIST;
}
renameat(tmp_name, client_name);
}
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit fe8b4617ddc1663d57ab5b0ffdeedb413e19a506
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Aug 7 13:14:23 2024 +0200
s3:vfs_default: implement VFS_RENAME_HOW_NO_REPLACE in vfswrap_renameat()
We can use renameat2() without ifdef as libreplace always provides it.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit adc8dea944bd26186814bf3dae9a300957532d93
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Aug 7 13:05:07 2024 +0200
s3:vfs: add VFS_RENAME_HOW_NO_REPLACE
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 5b305d1fbb2778f8c8dd2873e79f28a27d8ce581
Author: Stefan Metzmacher <metze at samba.org>
Date: Tue Aug 6 13:21:34 2024 +0200
s3:vfs: add vfs_rename_how to SMB_VFS_RENAMEAT()
This will support renameat2-like operations in future.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit f6550e804ea5604b1d7ec67e629fad8baee87f8b
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Aug 7 13:01:48 2024 +0200
lib/replace: add renameat2() replacement
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 7baeeece2dd563d404352e5f3e34661d1cbc2b03
Author: Stefan Metzmacher <metze at samba.org>
Date: Thu Aug 1 14:37:55 2024 +0200
s3:smbd: let mkdir_internal() work more atomically using a temporary name
Currently we do this in mkdir_internal():
mkdirat(client_name);
if (EEXIST) {
return EEXIST;
}
prepare_acls(client_name);
Note 'prepare_acls()' is a placeholder for the complex steps
it is doing to prepare the directory. During these steps
we have the problem that other clients already see
the directory and are able to create files or subdirectories
in it and these may not inherit the correct acls as
the their parent directory is not created completely.
I think I found a good strategie even without relying on
renameat2(RENAME_NOREPLACE).
We would do this instead:
tmp_name = ".::TMPNAME:D:$PID:client_name"
mkdirat(tmp_name, mode=client_mode);
prepare_acls(tmp_name);
mkdirat(client_name, mode=0);
if (EEXIST) {
unlinkat(tmp_name);
return EEXIST;
}
renameat(tmp_name, client_name);
So instead of having a long windows during prepare_acls,
we just have a short window between mkdirat(client_name, mode=0)
and renameat(tmp_name, client_name);
And in that short window the directory with the client_name
has a mode of 0, so it's not possible for other clients
to create files or subdirs in it.
As the mkdirat(client_name, mode=0) still catches
EEXIST the race where two clients try to create
the same client_name is closed as before,
so we don't need any other protection.
Following patches will make use of renameat2(RENAME_NOREPLACE),
but this already a very good improvement.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 460e280d3af70c38b04219e414ea3b6439caaed6
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 9 11:08:17 2024 +0200
docs-xml: add 'vfs mkdir use tmp name' option
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit f8be83a0a3302bc1802a34c03c49a774c56d7194
Author: Stefan Metzmacher <metze at samba.org>
Date: Thu Aug 1 14:37:55 2024 +0200
s3:smbd: improve DEBUG messages in mkdir_internal()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 5d077cd442116cc2304f4eba67e140be80c8db7a
Author: Stefan Metzmacher <metze at samba.org>
Date: Thu Aug 1 14:37:55 2024 +0200
s3:smbd: let mkdir_internal() use a talloc_stackframe()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 23f85e60ec9e806a82d2c33e905be9bad9c26db7
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 9 17:52:25 2024 +0200
s3:smbd: call apply_new_nt_acl() already in mkdir_internals()
We should have preparation steps as close as possible together.
We could move it for files as well, but that's a task for another
day...
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 75fe450f98c35095007a867de45286bbbd4251b0
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 9 17:52:25 2024 +0200
s3:smbd: split out apply_new_nt_acl() helper
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 30ddbe4611c39af40ce946d6e5693ee07553df5b
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 2 08:25:16 2024 +0200
lib/util: let server_id_str_buf_unique() use server_id_buf
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 20431cc62272f228023297a09eb256263184fa63
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 2 08:25:16 2024 +0200
lib/util: split out server_id_from_string_ex allow the unique delimiter to be passed in
In future it also allows to specifiy another delemiter than '/'
in order to use the resulting buffer as part of a file/directory
name.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 86952314036e5b6395f113c5968df794f5f95574
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 2 08:25:16 2024 +0200
lib/util: add server_id_str_buf_unique_ex() and allow the delimiter to be passed in
This way the server_id_str_buf() can just be a tiny wrapper using
'\0' as delemiter.
In future it also allows to specifiy another delemiter than '/'
in order to use the resulting buffer as part of a file/directory
name.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit c815128caa7acb0b1359b6a69e9033ce74d77c41
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 2 08:25:16 2024 +0200
lib/util: let server_id_str_buf() use PRIu32 and PRIu64
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 87aa3a46a3df36aeccdc5c93364fe1e71166c8fd
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 2 08:25:16 2024 +0200
lib/util: add a comment to struct server_id_buf
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit f9d7a930f00b0ac8848d87b3ff07997c477de5f9
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 9 11:06:00 2024 +0200
s4:torture/smb2: add smb2.create.mkdir-visible
This reproduces a race where one client creates
a directory and other clients see it before
the directory is fully setup including the correct
permissions and similar things.
We have a DENY ACE for SEC_DIR_ADD_FILE, which means
that files can't be created. This is set on
a base directory 'mkdir_visible'.
Then we have a lot of async loops trying to create
a file called 'mkdir_visible\dir\file_NR'. These loop
as fast as possible expecting OBJECT_PATH_NOT_FOUND,
because 'mkdir_visible\dir' is not there.
Then we send a create for 'mkdir_visible\dir' and
expect that to work.
This should turn the 'mkdir_visible\dir\file_NR' loop
into getting ACCESS_DENIED, because the
DENY ACE for SEC_DIR_ADD_FILE should be inherited
before 'mkdir_visible\dir' is visible to other clients.
Because of the complex steps in mkdir_internal(),
smbd allows the creation 'mkdir_visible\dir\file_NR',
as 'mkdir_visible\dir' is already visible after the
mkdirat(), before the DENY ACE is inherited.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
-----------------------------------------------------------------------
Summary of changes:
WHATSNEW.txt | 1 +
docs-xml/smbdotconf/vfs/vfsmkdirusetmpname.xml | 47 +++
examples/VFS/skel_opaque.c | 3 +-
examples/VFS/skel_transparent.c | 6 +-
lib/param/loadparm.c | 2 +
lib/replace/replace.c | 60 ++++
lib/replace/system/filesys.h | 29 ++
lib/replace/wscript | 2 +-
lib/util/server_id.c | 91 +++---
lib/util/server_id.h | 29 +-
lib/util/server_id_db.c | 12 +-
source3/include/vfs.h | 20 +-
source3/include/vfs_macros.h | 8 +-
source3/modules/vfs_audit.c | 6 +-
source3/modules/vfs_cap.c | 6 +-
source3/modules/vfs_catia.c | 6 +-
source3/modules/vfs_ceph.c | 8 +-
source3/modules/vfs_ceph_new.c | 8 +-
source3/modules/vfs_ceph_snapshots.c | 6 +-
source3/modules/vfs_crossrename.c | 6 +-
source3/modules/vfs_default.c | 23 +-
source3/modules/vfs_extd_audit.c | 6 +-
source3/modules/vfs_fruit.c | 9 +-
source3/modules/vfs_full_audit.c | 6 +-
source3/modules/vfs_glusterfs.c | 15 +-
source3/modules/vfs_media_harmony.c | 9 +-
source3/modules/vfs_not_implemented.c | 9 +-
source3/modules/vfs_recycle.c | 4 +-
source3/modules/vfs_shadow_copy2.c | 6 +-
source3/modules/vfs_snapper.c | 6 +-
source3/modules/vfs_streams_depot.c | 21 +-
source3/modules/vfs_streams_xattr.c | 11 +-
source3/modules/vfs_syncops.c | 6 +-
source3/modules/vfs_time_audit.c | 6 +-
source3/modules/vfs_unityed_media.c | 9 +-
source3/modules/vfs_virusfilter.c | 6 +-
source3/modules/vfs_virusfilter_utils.c | 4 +-
source3/modules/vfs_worm.c | 5 +-
source3/param/loadparm.c | 1 +
source3/smbd/dir.c | 56 ++++
source3/smbd/globals.h | 9 +
source3/smbd/open.c | 417 +++++++++++++++++++++----
source3/smbd/proto.h | 1 +
source3/smbd/smb2_reply.c | 6 +-
source3/smbd/vfs.c | 6 +-
source3/torture/cmd_vfs.c | 4 +-
source4/torture/smb2/create.c | 394 +++++++++++++++++++++++
47 files changed, 1235 insertions(+), 176 deletions(-)
create mode 100644 docs-xml/smbdotconf/vfs/vfsmkdirusetmpname.xml
Changeset truncated at 500 lines:
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 306cb28a19d..d034ce2ec84 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -26,6 +26,7 @@ smb.conf changes
Parameter Name Description Default
-------------- ----------- -------
+ vfs mkdir use tmp name New Auto
KNOWN ISSUES
diff --git a/docs-xml/smbdotconf/vfs/vfsmkdirusetmpname.xml b/docs-xml/smbdotconf/vfs/vfsmkdirusetmpname.xml
new file mode 100644
index 00000000000..92a39f8f541
--- /dev/null
+++ b/docs-xml/smbdotconf/vfs/vfsmkdirusetmpname.xml
@@ -0,0 +1,47 @@
+<samba:parameter name="vfs mkdir use tmp name"
+ context="S"
+ type="enum"
+ enumlist="enum_bool_auto"
+ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+ <para>
+ Creating a new directory for an SMB client is a very complex task!
+ It includes things like inheriting permissions from the parent directory
+ and storing DOS attributes.
+ </para>
+
+ <para>
+ Other clients should not see the existence of the directory that
+ is in progress of being created!
+ </para>
+
+ <para>
+ This option is an enumerated type that controls the usage of a temporary directory name.
+ When this is set to <constant>yes</constant>,
+ the directory name will be prefixed with '.::TMPNAME:D:$SERVERID:' (where $SERVERID is
+ a unique identifier for the current process).
+ </para>
+
+ <para>
+ When this option is set to Auto (the default), the server uses a temporary directory name
+ if, at least, one of the following options
+ is effectively not set to <constant>no</constant>:
+ <smbconfoption name="inherit acls"/>,
+ <smbconfoption name="inherit owner"/>,
+ <smbconfoption name="inherit permissions"/>,
+ <smbconfoption name="nt acl support"/> or
+ <smbconfoption name="store dos attributes"/>.
+ </para>
+
+ <para>
+ A re-export of an SMB/CIFS mount might one rare case where
+ <command moreinfo="none">vfs mkdir use tmp name = no</command> could be useful.
+ </para>
+
+ <para>
+ In most cases <command moreinfo="none">vfs mkdir use tmp name = Auto</command> should be kept.
+ </para>
+</description>
+<value type="default">Auto</value>
+</samba:parameter>
+
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index 255fa830402..a3521982f16 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -298,7 +298,8 @@ static int skel_renameat(vfs_handle_struct *handle,
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
errno = ENOSYS;
return -1;
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index 461228f09af..4d1312414a0 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -384,13 +384,15 @@ static int skel_renameat(vfs_handle_struct *handle,
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
return SMB_VFS_NEXT_RENAMEAT(handle,
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
}
struct skel_fsync_state {
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index ed5160d547b..047c59d3c6b 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -3095,6 +3095,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
lpcfg_do_global_parameter(lp_ctx, "store dos attributes", "yes");
+ lpcfg_do_global_parameter(lp_ctx, "vfs mkdir use tmp name", "Auto");
+
lpcfg_do_global_parameter(lp_ctx, "debug encryption", "no");
lpcfg_do_global_parameter(lp_ctx, "spotlight backend", "noindex");
diff --git a/lib/replace/replace.c b/lib/replace/replace.c
index 0b4e06d8bd5..359f43352bd 100644
--- a/lib/replace/replace.c
+++ b/lib/replace/replace.c
@@ -1171,3 +1171,63 @@ long rep_openat2(int dirfd, const char *pathname,
#endif
}
#endif /* !HAVE_OPENAT2 */
+
+#ifndef HAVE_RENAMEAT2
+
+/* fallback to wellknown __NR_renameat2 values */
+#ifndef __NR_renameat2
+# if defined(LINUX) && defined(HAVE_SYS_SYSCALL_H)
+# if defined(__i386__)
+# define __NR_renameat2 353
+# elif defined(__x86_64__) && defined(__LP64__)
+# define __NR_renameat2 316 /* 316 0x13C */
+# elif defined(__x86_64__) && defined(__ILP32__)
+# define __NR_renameat2 1073742140 /* 1073742140 0x4000013C */
+# elif defined(__aarch64__)
+# define __NR_renameat2 276
+# elif defined(__arm__)
+# define __NR_renameat2 382
+# elif defined(__sparc__)
+# define __NR_renameat2 345
+# endif
+# endif /* defined(LINUX) && defined(HAVE_SYS_SYSCALL_H) */
+#endif /* !__NR_renameat2 */
+
+#ifdef DISABLE_OPATH
+/*
+ * systems without O_PATH also don't have renameat2,
+ * so make sure we at a realistic combination.
+ */
+#undef __NR_renameat2
+#endif /* DISABLE_OPATH */
+
+int rep_renameat2(int __oldfd, const char *__old, int __newfd,
+ const char *__new, unsigned int __flags)
+{
+ if (__flags != 0) {
+#ifdef __NR_renameat2
+ int ret;
+
+ ret = syscall(__NR_renameat2,
+ __oldfd,
+ __old,
+ __newfd,
+ __new,
+ __flags);
+ if (ret != -1 || errno != ENOSYS) {
+ /*
+ * if it's ENOSYS, we fallback
+ * to EINVAL below, otherwise
+ * we return what the kernel
+ * did.
+ */
+ return ret;
+ }
+#endif
+ errno = EINVAL;
+ return -1;
+ }
+
+ return renameat(__oldfd, __old, __newfd, __new);
+}
+#endif /* ! HAVE_RENAMEAT2 */
diff --git a/lib/replace/system/filesys.h b/lib/replace/system/filesys.h
index 8005b18780f..9738ad52935 100644
--- a/lib/replace/system/filesys.h
+++ b/lib/replace/system/filesys.h
@@ -278,4 +278,33 @@ long rep_openat2(int dirfd, const char *pathname,
rep_openat2(dirfd, pathname, how, size)
#endif /* !HAVE_OPENAT2 */
+#ifdef DISABLE_OPATH
+/*
+ * Without O_PATH, the kernel
+ * most likely doesn't have renameat2() too
+ * and we should test the fallback code
+ */
+#undef HAVE_RENAMEAT2
+#endif
+
+#ifndef HAVE_RENAMEAT2
+
+#ifndef RENAME_NOREPLACE
+# define RENAME_NOREPLACE (1 << 0)
+#endif
+
+#ifndef RENAME_EXCHANGE
+# define RENAME_EXCHANGE (1 << 1)
+#endif
+
+#ifndef RENAME_WHITEOUT
+# define RENAME_WHITEOUT (1 << 2)
+#endif
+
+int rep_renameat2(int __oldfd, const char *__old, int __newfd,
+ const char *__new, unsigned int __flags);
+#define renameat2(__oldfd, __old, __newfd, __new, __flags) \
+ rep_renameat2(__oldfd, __old, __newfd, __new, __flags)
+#endif /* !HAVE_RENAMEAT2 */
+
#endif
diff --git a/lib/replace/wscript b/lib/replace/wscript
index 77e655bb68b..f5114b69ffc 100644
--- a/lib/replace/wscript
+++ b/lib/replace/wscript
@@ -422,7 +422,7 @@ def configure(conf):
conf.CHECK_FUNCS('link readlink symlink realpath snprintf vsnprintf')
conf.CHECK_FUNCS('asprintf vasprintf setenv unsetenv strnlen strtoull __strtoull')
conf.CHECK_FUNCS('strtouq strtoll __strtoll strtoq memalign posix_memalign')
- conf.CHECK_FUNCS('fmemopen')
+ conf.CHECK_FUNCS('fmemopen renameat2')
if conf.CONFIG_SET('HAVE_MEMALIGN'):
conf.CHECK_DECLS('memalign', headers='malloc.h')
diff --git a/lib/util/server_id.c b/lib/util/server_id.c
index 690b9ddfbdc..2370163da80 100644
--- a/lib/util/server_id.c
+++ b/lib/util/server_id.c
@@ -55,55 +55,62 @@ bool server_id_equal(const struct server_id *p1, const struct server_id *p2)
char *server_id_str_buf(struct server_id id, struct server_id_buf *dst)
{
+ return server_id_str_buf_unique_ex(id, '\0', dst);
+}
+
+char *server_id_str_buf_unique_ex(struct server_id id,
+ char unique_delimiter,
+ struct server_id_buf *dst)
+{
+ if (id.unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) {
+ unique_delimiter = '\0';
+ }
+
if (server_id_is_disconnected(&id)) {
strlcpy(dst->buf, "disconnected", sizeof(dst->buf));
} else if ((id.vnn == NONCLUSTER_VNN) && (id.task_id == 0)) {
- snprintf(dst->buf, sizeof(dst->buf), "%llu",
- (unsigned long long)id.pid);
+ snprintf(dst->buf, sizeof(dst->buf),
+ "%"PRIu64"%c%"PRIu64"",
+ id.pid, unique_delimiter, id.unique_id);
} else if (id.vnn == NONCLUSTER_VNN) {
- snprintf(dst->buf, sizeof(dst->buf), "%llu.%u",
- (unsigned long long)id.pid, (unsigned)id.task_id);
+ snprintf(dst->buf, sizeof(dst->buf),
+ "%"PRIu64".%"PRIu32"%c%"PRIu64"",
+ id.pid, id.task_id,
+ unique_delimiter, id.unique_id);
} else if (id.task_id == 0) {
- snprintf(dst->buf, sizeof(dst->buf), "%u:%llu",
- (unsigned)id.vnn, (unsigned long long)id.pid);
+ snprintf(dst->buf, sizeof(dst->buf),
+ "%"PRIu32":%"PRIu64"%c%"PRIu64"",
+ id.vnn, id.pid,
+ unique_delimiter, id.unique_id);
} else {
- snprintf(dst->buf, sizeof(dst->buf), "%u:%llu.%u",
- (unsigned)id.vnn,
- (unsigned long long)id.pid,
- (unsigned)id.task_id);
+ snprintf(dst->buf, sizeof(dst->buf),
+ "%"PRIu32":%"PRIu64".%"PRIu32"%c%"PRIu64"",
+ id.vnn, id.pid, id.task_id,
+ unique_delimiter, id.unique_id);
}
return dst->buf;
}
-size_t server_id_str_buf_unique(struct server_id id, char *buf, size_t buflen)
+char *server_id_str_buf_unique(struct server_id id, struct server_id_buf *dst)
{
- struct server_id_buf idbuf;
- char unique_buf[21]; /* 2^64 is 18446744073709551616, 20 chars */
- size_t idlen, unique_len, needed;
-
- server_id_str_buf(id, &idbuf);
-
- idlen = strlen(idbuf.buf);
- unique_len = snprintf(unique_buf, sizeof(unique_buf), "%"PRIu64,
- id.unique_id);
- needed = idlen + unique_len + 2;
-
- if (buflen >= needed) {
- memcpy(buf, idbuf.buf, idlen);
- buf[idlen] = '/';
- memcpy(buf + idlen + 1, unique_buf, unique_len+1);
- }
-
- return needed;
+ return server_id_str_buf_unique_ex(id, '/', dst);
}
struct server_id server_id_from_string(uint32_t local_vnn,
const char *pid_string)
+{
+ return server_id_from_string_ex(local_vnn, '/', pid_string);
+}
+
+struct server_id server_id_from_string_ex(uint32_t local_vnn,
+ char unique_delimiter,
+ const char *pid_string)
{
struct server_id templ = {
.vnn = NONCLUSTER_VNN, .pid = UINT64_MAX
};
struct server_id result;
+ char unique_delimiter_found = '\0';
int ret;
/*
@@ -114,10 +121,10 @@ struct server_id server_id_from_string(uint32_t local_vnn,
*/
result = templ;
- ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32"/%"SCNu64,
+ ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32"%c%"SCNu64,
&result.vnn, &result.pid, &result.task_id,
- &result.unique_id);
- if (ret == 4) {
+ &unique_delimiter_found, &result.unique_id);
+ if (ret == 5 && unique_delimiter_found == unique_delimiter) {
return result;
}
@@ -129,9 +136,10 @@ struct server_id server_id_from_string(uint32_t local_vnn,
}
result = templ;
- ret = sscanf(pid_string, "%"SCNu32":%"SCNu64"/%"SCNu64,
- &result.vnn, &result.pid, &result.unique_id);
- if (ret == 3) {
+ ret = sscanf(pid_string, "%"SCNu32":%"SCNu64"%c%"SCNu64,
+ &result.vnn, &result.pid,
+ &unique_delimiter_found, &result.unique_id);
+ if (ret == 4 && unique_delimiter_found == unique_delimiter) {
return result;
}
@@ -143,9 +151,10 @@ struct server_id server_id_from_string(uint32_t local_vnn,
}
result = templ;
- ret = sscanf(pid_string, "%"SCNu64".%"SCNu32"/%"SCNu64,
- &result.pid, &result.task_id, &result.unique_id);
- if (ret == 3) {
+ ret = sscanf(pid_string, "%"SCNu64".%"SCNu32"%c%"SCNu64,
+ &result.pid, &result.task_id,
+ &unique_delimiter_found, &result.unique_id);
+ if (ret == 4 && unique_delimiter_found == unique_delimiter) {
result.vnn = local_vnn;
return result;
}
@@ -159,9 +168,9 @@ struct server_id server_id_from_string(uint32_t local_vnn,
}
result = templ;
- ret = sscanf(pid_string, "%"SCNu64"/%"SCNu64,
- &result.pid, &result.unique_id);
- if (ret == 2) {
+ ret = sscanf(pid_string, "%"SCNu64"%c%"SCNu64,
+ &result.pid, &unique_delimiter_found, &result.unique_id);
+ if (ret == 3 && unique_delimiter_found == unique_delimiter) {
result.vnn = local_vnn;
return result;
}
diff --git a/lib/util/server_id.h b/lib/util/server_id.h
index 5b723d5cda4..c9630b7f774 100644
--- a/lib/util/server_id.h
+++ b/lib/util/server_id.h
@@ -24,17 +24,42 @@
struct server_id;
-struct server_id_buf { char buf[48]; }; /* probably a bit too large ... */
+struct server_id_buf {
+ /*
+ * 4294967295 uses 10 chars
+ * 18446744073709551615 uses 20 chars
+ *
+ * We have these combinations:
+ * - "disconnected"
+ * - PID64
+ * - PID64.TASK32
+ * - VNN32:PID64.TASK32
+ *
+ * The largest has 10 + 1 + 20 + 1 + 10 + 1 = 43 chars
+ *
+ * Optionally we allow :UNIQUE64 added,
+ * which adds 21 chars, so we are at 64 chars
+ * and that's 8 byte aligned.
+ */
+ char buf[64];
+};
bool server_id_same_process(const struct server_id *p1,
const struct server_id *p2);
int server_id_cmp(const struct server_id *p1, const struct server_id *p2);
bool server_id_equal(const struct server_id *p1, const struct server_id *p2);
char *server_id_str_buf(struct server_id id, struct server_id_buf *dst);
-size_t server_id_str_buf_unique(struct server_id id, char *buf, size_t buflen);
+char *server_id_str_buf_unique_ex(struct server_id id,
+ char unique_delimiter,
+ struct server_id_buf *dst);
+char *server_id_str_buf_unique(struct server_id id,
+ struct server_id_buf *dst);
struct server_id server_id_from_string(uint32_t local_vnn,
const char *pid_string);
+struct server_id server_id_from_string_ex(uint32_t local_vnn,
+ char unique_delimiter,
+ const char *pid_string);
/**
* Set the serverid to the special value that represents a disconnected
diff --git a/lib/util/server_id_db.c b/lib/util/server_id_db.c
index 17b157706b4..c5cbdee9eef 100644
--- a/lib/util/server_id_db.c
+++ b/lib/util/server_id_db.c
@@ -111,10 +111,9 @@ int server_id_db_add(struct server_id_db *db, const char *name)
key = string_term_tdb_data(name);
{
- size_t idlen = server_id_str_buf_unique(db->pid, NULL, 0);
- char idbuf[idlen];
-
- server_id_str_buf_unique(db->pid, idbuf, idlen);
+ struct server_id_buf _buf;
+ char *idbuf = server_id_str_buf_unique(db->pid, &_buf);
+ size_t idlen = strlen(idbuf) + 1;
ret = tdb_append(
tdb, key,
@@ -134,8 +133,8 @@ int server_id_db_prune_name(struct server_id_db *db, const char *name,
struct server_id server)
{
struct tdb_context *tdb = db->tdb->tdb;
- size_t idbuf_len = server_id_str_buf_unique(server, NULL, 0);
- char idbuf[idbuf_len];
+ struct server_id_buf _buf;
+ char *idbuf = server_id_str_buf_unique(server, &_buf);
TDB_DATA key;
uint8_t *data;
size_t datalen;
@@ -143,7 +142,6 @@ int server_id_db_prune_name(struct server_id_db *db, const char *name,
int ret;
key = string_term_tdb_data(name);
- server_id_str_buf_unique(server, idbuf, idbuf_len);
ret = tdb_chainlock(tdb, key);
if (ret == -1) {
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 374d7e03c33..75e4d8f816d 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -381,9 +381,12 @@
* Change to Version 49 - will ship with 4.19
* Version 49 - remove seekdir and telldir
* Version 49 - remove "sbuf" argument from readdir_fn()
+ * Change to Version 50 - will ship with 4.22
+ * Version 50 - Change SMB_VFS_RENAMEAT() add vfs_rename_how
+ * Version 50 - Add VFS_RENAME_HOW_NO_REPLACE to vfs_rename_how
*/
-#define SMB_VFS_INTERFACE_VERSION 49
+#define SMB_VFS_INTERFACE_VERSION 50
/*
All intercepted VFS operations must be declared as static functions inside module source
@@ -918,6 +921,12 @@ struct vfs_open_how {
uint64_t resolve;
};
+#define VFS_RENAME_HOW_NO_REPLACE 1
+
+struct vfs_rename_how {
+ int flags;
+};
+
/*
Available VFS operations. These values must be in sync with vfs_ops struct
--
Samba Shared Repository
More information about the samba-cvs
mailing list