[PATCH]: Add VFS functions for setting and getting DOS attributes.

Jeremy Allison jra at samba.org
Fri Mar 25 23:50:39 UTC 2016


On Wed, Mar 23, 2016 at 10:02:05PM -0700, Jeremy Allison wrote:
> On Wed, Mar 23, 2016 at 09:54:15PM -0700, Richard Sharpe wrote:
> > Hi folks,
> > 
> > I think this is getting closer.
> > 
> > However, I still have to deal with one of Uri's concerns (the
> > fget_dos_attr function).
> > 
> > I also used discard_const to squash an annoying error message. I plan
> > to submit another patch to constify some more struct smb_filenames ..
> 
> > @@ -309,11 +309,12 @@ static bool get_ea_dos_attribute(connection_struct *conn,
> >  		case 1:
> >  			dosattr = dosattrib.info.info1.attrib;
> >  			if (!null_nttime(dosattrib.info.info1.create_time)) {
> > +				struct smb_filename *fname = discard_const(smb_fname);
> >  				struct timespec create_time =
> >  					nt_time_to_unix_timespec(
> >  						dosattrib.info.info1.create_time);
> 
> I don't think using discard_const is the right thing to
> do here.

OK - here is a revised version I'm happy with.

It does leave the (currently) unused call
SMB_VFS_FGET_DOS_ATTRIBUTES() as one thing
I've learned is never to put half an interface
into the VFS - even if currently unused someone
will need it soon.

I'm not too worried at the moment about the
FXXX calls not using the fsp->fh->fd right
now. Now we have the right interface in the
upper level code, we can move to the correct
calls in the lower level code at our leisure,
and I think Richard designed the correct VFS
interface here.

Firstly it splits the patch into 2. Part 1
updates the VFS, part 2 implements the changes
in dosmode.c.

Secondly, the semantics of the existing code
are such that get_dos_attribute is *expected*
to change the create time value in the struct
stat inside the passed in smb_filename struct,
so the new VFS call SMB_VFS_GET_DOS_ATTRIBUTES()
can't take a const struct smb_filename *.

See the (unchanged in this patch) comment here:

/****************************************************************************
 Get DOS attributes from an EA.
 This can also pull the create time into the stat struct inside smb_fname.
****************************************************************************/

NTSTATUS get_ea_dos_attribute(connection_struct *conn,
                              struct smb_filename *smb_fname,
                              uint32_t *pattr)

This kind of sucks, it means get_ea_dos_attributes
returns 2 values, the uint32_t *pattr and the updated
time inside struct smb_filename *smb_fname. But
to keep current smbd working it needs to stay that
way at least for now.

A later patch could change get_ea_dos_attribute()
to also return a non-const pointer to a struct stat to
put the create time in and ensure it gets copied
into where it needs to be, but thats too big a change to
make here I think. At that point we could change
SMB_VFS_GET_DOS_ATTRIBUTES() to take another arg.

Please reivew and push if happy !

Cheers,

Jeremy.
-------------- next part --------------
From e556676d474bf7c3ce7f27c10d9e67bb4c455a27 Mon Sep 17 00:00:00 2001
From: Richard Sharpe <rsharpe at samba.org>
Date: Sun, 20 Mar 2016 12:51:32 -0700
Subject: [PATCH 1/2] s3: vfs: Add VFS functions for setting and getting DOS
 attributes.

This will make it easier to support those systems and file systems that
can store DOS attributes. It should retain the original functionality if
VFS functions providing these things are not provided.

Signed-off-by: Richard Sharpe <rsharpe at samba.org>
Signed-off-by: Jeremy Allison <jra at samba.org>
---
 examples/VFS/skel_opaque.c       | 34 +++++++++++++++
 examples/VFS/skel_transparent.c  | 42 ++++++++++++++++++
 source3/include/vfs.h            | 29 +++++++++++++
 source3/include/vfs_macros.h     | 18 ++++++++
 source3/modules/vfs_default.c    | 32 ++++++++++++++
 source3/modules/vfs_full_audit.c | 94 ++++++++++++++++++++++++++++++++++++++++
 source3/smbd/proto.h             |  7 +++
 source3/smbd/vfs.c               | 32 ++++++++++++++
 8 files changed, 288 insertions(+)

diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index 67c387d..81ce184 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -672,6 +672,34 @@ static NTSTATUS skel_readdir_attr(struct vfs_handle_struct *handle,
 	return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS skel_get_dos_attributes(struct vfs_handle_struct *handle,
+				struct smb_filename *smb_fname,
+				uint32_t *dosmode)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS skel_fget_dos_attributes(struct vfs_handle_struct *handle,
+				struct files_struct *fsp,
+				uint32_t *dosmode)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS skel_set_dos_attributes(struct vfs_handle_struct *handle,
+				const struct smb_filename *smb_fname,
+				uint32_t dosmode)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS skel_fset_dos_attributes(struct vfs_handle_struct *handle,
+				struct files_struct *fsp,
+				uint32_t dosmode)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
 static NTSTATUS skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
 				 uint32_t security_info,
 				 TALLOC_CTX *mem_ctx,
@@ -941,6 +969,12 @@ struct vfs_fn_pointers skel_opaque_fns = {
 	.fsctl_fn = skel_fsctl,
 	.readdir_attr_fn = skel_readdir_attr,
 
+	/* DOS attributes. */
+	.get_dos_attributes_fn = skel_get_dos_attributes,
+	.fget_dos_attributes_fn = skel_fget_dos_attributes,
+	.set_dos_attributes_fn = skel_set_dos_attributes,
+	.fset_dos_attributes_fn = skel_fset_dos_attributes,
+
 	/* NT ACL operations. */
 
 	.fget_nt_acl_fn = skel_fget_nt_acl,
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index 9fc9438..418ee24 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -801,6 +801,42 @@ static NTSTATUS skel_readdir_attr(struct vfs_handle_struct *handle,
 	return SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data);
 }
 
+static NTSTATUS skel_get_dos_attributes(struct vfs_handle_struct *handle,
+				struct smb_filename *smb_fname,
+				uint32_t *dosmode)
+{
+	return SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle,
+				smb_fname,
+				dosmode);
+}
+
+static NTSTATUS skel_fget_dos_attributes(struct vfs_handle_struct *handle,
+				struct files_struct *fsp,
+				uint32_t *dosmode)
+{
+	return SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle,
+				fsp,
+				dosmode);
+}
+
+static NTSTATUS skel_set_dos_attributes(struct vfs_handle_struct *handle,
+				const struct smb_filename *smb_fname,
+				uint32_t dosmode)
+{
+	return SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle,
+				smb_fname,
+				dosmode);
+}
+
+static NTSTATUS skel_fset_dos_attributes(struct vfs_handle_struct *handle,
+				struct files_struct *fsp,
+				uint32_t dosmode)
+{
+	return SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle,
+				fsp,
+				dosmode);
+}
+
 static NTSTATUS skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
 				 uint32_t security_info,
 				 TALLOC_CTX *mem_ctx,
@@ -1056,6 +1092,12 @@ struct vfs_fn_pointers skel_transparent_fns = {
 	.fsctl_fn = skel_fsctl,
 	.readdir_attr_fn = skel_readdir_attr,
 
+	/* DOS attributes. */
+	.get_dos_attributes_fn = skel_get_dos_attributes,
+	.fget_dos_attributes_fn = skel_fget_dos_attributes,
+	.set_dos_attributes_fn = skel_set_dos_attributes,
+	.fset_dos_attributes_fn = skel_fset_dos_attributes,
+
 	/* NT ACL operations. */
 
 	.fget_nt_acl_fn = skel_fget_nt_acl,
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 3a86c62..6ab9a7e 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -191,6 +191,7 @@
 /* Version 35 - Change streaminfo from const char *, to
 		const struct smb_filename * */
 /* Version 35 - Add uint32_t flags to struct smb_filename */
+/* Version 35 - Add get/set/fget/fset dos attribute functions. */
 
 #define SMB_VFS_INTERFACE_VERSION 35
 
@@ -785,6 +786,22 @@ struct vfs_fn_pointers {
 			     uint32_t max_out_len,
 			     uint32_t *out_len); 
 
+	NTSTATUS (*get_dos_attributes_fn)(struct vfs_handle_struct *handle,
+					  struct smb_filename *smb_fname,
+					  uint32_t *dosmode);
+
+	NTSTATUS (*fget_dos_attributes_fn)(struct vfs_handle_struct *handle,
+					   struct files_struct *fsp,
+					   uint32_t *dosmode);
+
+	NTSTATUS (*set_dos_attributes_fn)(struct vfs_handle_struct *handle,
+					  const struct smb_filename *smb_fname,
+					  uint32_t dosmode);
+
+	NTSTATUS (*fset_dos_attributes_fn)(struct vfs_handle_struct *hande,
+					   struct files_struct *fsp,
+					   uint32_t dosmode);
+
 	/* NT ACL operations. */
 
 	NTSTATUS (*fget_nt_acl_fn)(struct vfs_handle_struct *handle,
@@ -1205,6 +1222,18 @@ NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
 			    uint8_t **_out_data,
 			    uint32_t max_out_len,
 			    uint32_t *out_len);
+NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
+					 struct smb_filename *smb_fname,
+					 uint32_t *dosmode);
+NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
+					  struct files_struct *fsp,
+					  uint32_t *dosmode);
+NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
+					 const struct smb_filename *smb_fname,
+					 uint32_t dosmode);
+NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
+					  struct files_struct *fsp,
+					  uint32_t dosmode);
 struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
 						TALLOC_CTX *mem_ctx,
 						struct tevent_context *ev,
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index 6059c2a..c3c9a17 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -397,6 +397,24 @@
 #define SMB_VFS_NEXT_FSCTL(handle, fsp, ctx, function, req_flags, in_data, in_len, out_data, max_out_len, out_len) \
 	smb_vfs_call_fsctl((handle)->next, (fsp), (ctx), (function), (req_flags), (in_data), (in_len), (out_data), (max_out_len), (out_len))
 
+#define SMB_VFS_GET_DOS_ATTRIBUTES(conn, smb_fname, attributes) \
+	smb_vfs_call_get_dos_attributes((conn)->vfs_handles, (smb_fname), (attributes))
+#define SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle, smb_fname, attributes) \
+	smb_vfs_call_get_dos_attributes((handle)->next, (smb_fname), (attributes))
+#define SMB_VFS_FGET_DOS_ATTRIBUTES(conn, fsp, attributes) \
+	smb_vfs_call_fget_dos_attributes((conn)->vfs_handles, (fsp), (attributes))
+#define SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, attributes) \
+	smb_vfs_call_fget_dos_attributes((handle)->next, (fsp), (attributes))
+
+#define SMB_VFS_SET_DOS_ATTRIBUTES(conn, smb_fname, attributes) \
+	smb_vfs_call_set_dos_attributes((conn)->vfs_handles, (smb_fname), (attributes))
+#define SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle, smb_fname, attributes) \
+	smb_vfs_call_set_dos_attributes((handle)->next, (smb_fname), (attributes))
+#define SMB_VFS_FSET_DOS_ATTRIBUTES(conn, fsp, attributes) \
+	smb_vfs_call_fset_dos_attributes((conn)->vfs_handles, (fsp), (attributes))
+#define SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle, fsp, attributes) \
+	smb_vfs_call_fset_dos_attributes((handle)->next, (fsp), (attributes))
+
 #define SMB_VFS_COPY_CHUNK_SEND(conn, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num) \
 	smb_vfs_call_copy_chunk_send((conn)->vfs_handles, (mem_ctx), (ev), (src_fsp), (src_off), (dest_fsp), (dest_off), (num))
 #define SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, mem_ctx, ev, src_fsp, src_off, dest_fsp, dest_off, num) \
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 41e443e..8ee1635 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1427,6 +1427,34 @@ static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
 	return NT_STATUS_NOT_SUPPORTED;
 }
 
+static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
+					   struct smb_filename *smb_fname,
+					   uint32_t *dosmode)
+{
+	return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
+}
+
+static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
+					    struct files_struct *fsp,
+					    uint32_t *dosmode)
+{
+	return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
+}
+
+static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
+					   const struct smb_filename *smb_fname,
+					   uint32_t dosmode)
+{
+	return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
+}
+
+static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
+					    struct files_struct *fsp,
+					    uint32_t dosmode)
+{
+	return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
+}
+
 struct vfs_cc_state {
 	off_t copied;
 	uint8_t *buf;
@@ -2649,6 +2677,10 @@ static struct vfs_fn_pointers vfs_default_fns = {
 	.strict_unlock_fn = vfswrap_strict_unlock,
 	.translate_name_fn = vfswrap_translate_name,
 	.fsctl_fn = vfswrap_fsctl,
+	.set_dos_attributes_fn = vfswrap_set_dos_attributes,
+	.fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
+	.get_dos_attributes_fn = vfswrap_get_dos_attributes,
+	.fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
 	.copy_chunk_send_fn = vfswrap_copy_chunk_send,
 	.copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
 	.get_compression_fn = vfswrap_get_compression,
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index 691b1e1..0d36bbb 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -175,6 +175,12 @@ typedef enum _vfs_op_type {
 	SMB_VFS_OP_SET_COMPRESSION,
 	SMB_VFS_OP_READDIR_ATTR,
 
+	/* DOS attribute opeataions. */
+	SMB_VFS_OP_GET_DOS_ATTRIBUTES,
+	SMB_VFS_OP_FGET_DOS_ATTRIBUTES,
+	SMB_VFS_OP_SET_DOS_ATTRIBUTES,
+	SMB_VFS_OP_FSET_DOS_ATTRIBUTES,
+
 	/* NT ACL operations. */
 
 	SMB_VFS_OP_FGET_NT_ACL,
@@ -301,6 +307,10 @@ static struct {
 	{ SMB_VFS_OP_GET_COMPRESSION,	"get_compression" },
 	{ SMB_VFS_OP_SET_COMPRESSION,	"set_compression" },
 	{ SMB_VFS_OP_READDIR_ATTR,      "readdir_attr" },
+	{ SMB_VFS_OP_GET_DOS_ATTRIBUTES, "get_dos_attributes" },
+	{ SMB_VFS_OP_FGET_DOS_ATTRIBUTES, "fget_dos_attributes" },
+	{ SMB_VFS_OP_SET_DOS_ATTRIBUTES, "set_dos_attributes" },
+	{ SMB_VFS_OP_FSET_DOS_ATTRIBUTES, "fset_dos_attributes" },
 	{ SMB_VFS_OP_FGET_NT_ACL,	"fget_nt_acl" },
 	{ SMB_VFS_OP_GET_NT_ACL,	"get_nt_acl" },
 	{ SMB_VFS_OP_FSET_NT_ACL,	"fset_nt_acl" },
@@ -1895,6 +1905,86 @@ static NTSTATUS smb_full_audit_readdir_attr(struct vfs_handle_struct *handle,
 	return status;
 }
 
+static NTSTATUS smb_full_audit_get_dos_attributes(
+				struct vfs_handle_struct *handle,
+				struct smb_filename *smb_fname,
+				uint32_t *dosmode)
+{
+	NTSTATUS status;
+
+	status = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle,
+				smb_fname,
+				dosmode);
+
+	do_log(SMB_VFS_OP_GET_DOS_ATTRIBUTES,
+		NT_STATUS_IS_OK(status),
+		handle,
+		"%s",
+		smb_fname_str_do_log(smb_fname));
+
+	return status;
+}
+
+static NTSTATUS smb_full_audit_fget_dos_attributes(
+				struct vfs_handle_struct *handle,
+				struct files_struct *fsp,
+				uint32_t *dosmode)
+{
+	NTSTATUS status;
+
+	status = SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle,
+				fsp,
+				dosmode);
+
+	do_log(SMB_VFS_OP_FGET_DOS_ATTRIBUTES,
+		NT_STATUS_IS_OK(status),
+		handle,
+		"%s",
+		fsp_str_do_log(fsp));
+
+	return status;
+}
+
+static NTSTATUS smb_full_audit_set_dos_attributes(
+				struct vfs_handle_struct *handle,
+				const struct smb_filename *smb_fname,
+				uint32_t dosmode)
+{
+	NTSTATUS status;
+
+	status = SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle,
+				smb_fname,
+				dosmode);
+
+	do_log(SMB_VFS_OP_SET_DOS_ATTRIBUTES,
+		NT_STATUS_IS_OK(status),
+		handle,
+		"%s",
+		smb_fname_str_do_log(smb_fname));
+
+	return status;
+}
+
+static NTSTATUS smb_full_audit_fset_dos_attributes(
+				struct vfs_handle_struct *handle,
+				struct files_struct *fsp,
+				uint32_t dosmode)
+{
+	NTSTATUS status;
+
+	status = SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle,
+				fsp,
+				dosmode);
+
+	do_log(SMB_VFS_OP_FSET_DOS_ATTRIBUTES,
+		NT_STATUS_IS_OK(status),
+		handle,
+		"%s",
+		fsp_str_do_log(fsp));
+
+	return status;
+}
+
 static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
 					   uint32_t security_info,
 					   TALLOC_CTX *mem_ctx,
@@ -2314,6 +2404,10 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
 	.get_compression_fn = smb_full_audit_get_compression,
 	.set_compression_fn = smb_full_audit_set_compression,
 	.readdir_attr_fn = smb_full_audit_readdir_attr,
+	.get_dos_attributes_fn = smb_full_audit_get_dos_attributes,
+	.fget_dos_attributes_fn = smb_full_audit_fget_dos_attributes,
+	.set_dos_attributes_fn = smb_full_audit_set_dos_attributes,
+	.fset_dos_attributes_fn = smb_full_audit_fset_dos_attributes,
 	.fget_nt_acl_fn = smb_full_audit_fget_nt_acl,
 	.get_nt_acl_fn = smb_full_audit_get_nt_acl,
 	.fset_nt_acl_fn = smb_full_audit_fset_nt_acl,
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 4be6521..8e8cbc3 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -278,6 +278,13 @@ bool set_sticky_write_time_path(struct file_id fileid, struct timespec mtime);
 bool set_sticky_write_time_fsp(struct files_struct *fsp,
 			       struct timespec mtime);
 
+NTSTATUS get_ea_dos_attribute(connection_struct *conn,
+			      struct smb_filename *smb_fname,
+			      uint32_t *pattr);
+NTSTATUS set_ea_dos_attribute(connection_struct *conn,
+			      const struct smb_filename *smb_fname,
+			      uint32_t dosmode);
+
 NTSTATUS set_create_timespec_ea(connection_struct *conn,
 				const struct smb_filename *smb_fname,
 				struct timespec create_time);
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index b58becc..efed268 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -2202,6 +2202,38 @@ NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
 				     out_len);
 }
 
+NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
+					 struct smb_filename *smb_fname,
+					 uint32_t *dosmode)
+{
+	VFS_FIND(get_dos_attributes);
+	return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
+}
+
+NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
+					  struct files_struct *fsp,
+					  uint32_t *dosmode)
+{
+	VFS_FIND(fget_dos_attributes);
+	return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
+}
+
+NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
+					 const struct smb_filename *smb_fname,
+					 uint32_t dosmode)
+{
+	VFS_FIND(set_dos_attributes);
+	return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
+}
+
+NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
+					  struct files_struct *fsp,
+					  uint32_t dosmode)
+{
+	VFS_FIND(set_dos_attributes);
+	return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
+}
+
 struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
 						TALLOC_CTX *mem_ctx,
 						struct tevent_context *ev,
-- 
2.8.0.rc3.226.g39d4020


From 6bb59fd546d24d3b3df65646fc160bf3e1128e00 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 25 Mar 2016 15:32:09 -0700
Subject: [PATCH 2/2] s3: vfs: Use the new VFS functions for setting and
 getting DOS attributes.

This will make it easier to support those systems and file systems that
can store DOS attributes.

Signed-off-by: Richard Sharpe <rsharpe at samba.org>
Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/dosmode.c | 111 +++++++++++++++++++++++++++++--------------------
 1 file changed, 65 insertions(+), 46 deletions(-)

diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 60f2f68..f490e9a 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -27,7 +27,7 @@
 #include "lib/param/loadparm.h"
 
 static NTSTATUS get_file_handle_for_metadata(connection_struct *conn,
-				struct smb_filename *smb_fname,
+				const struct smb_filename *smb_fname,
 				files_struct **ret_fsp,
 				bool *need_close);
 
@@ -260,9 +260,9 @@ static uint32_t dos_mode_from_sbuf(connection_struct *conn,
  This can also pull the create time into the stat struct inside smb_fname.
 ****************************************************************************/
 
-static bool get_ea_dos_attribute(connection_struct *conn,
-				 struct smb_filename *smb_fname,
-				 uint32_t *pattr)
+NTSTATUS get_ea_dos_attribute(connection_struct *conn,
+			      struct smb_filename *smb_fname,
+			      uint32_t *pattr)
 {
 	struct xattr_DOSATTRIB dosattrib;
 	enum ndr_err_code ndr_err;
@@ -272,7 +272,7 @@ static bool get_ea_dos_attribute(connection_struct *conn,
 	uint32_t dosattr;
 
 	if (!lp_store_dos_attributes(SNUM(conn))) {
-		return False;
+		return NT_STATUS_NOT_IMPLEMENTED;
 	}
 
 	/* Don't reset pattr to zero as we may already have filename-based attributes we
@@ -285,7 +285,7 @@ static bool get_ea_dos_attribute(connection_struct *conn,
 		DBG_INFO("Cannot get attribute "
 			 "from EA on file %s: Error = %s\n",
 			 smb_fname_str_dbg(smb_fname), strerror(errno));
-		return False;
+		return map_nt_error_from_unix(errno);
 	}
 
 	blob.data = (uint8_t *)attrstr;
@@ -299,7 +299,7 @@ static bool get_ea_dos_attribute(connection_struct *conn,
 			 "from EA on file %s: Error = %s\n",
 			 smb_fname_str_dbg(smb_fname),
 			 ndr_errstr(ndr_err)));
-		return false;
+		return ndr_map_error2ntstatus(ndr_err);
 	}
 
 	DEBUG(10,("get_ea_dos_attribute: %s attr = %s\n",
@@ -352,7 +352,8 @@ static bool get_ea_dos_attribute(connection_struct *conn,
 			DEBUG(1,("get_ea_dos_attribute: Badly formed DOSATTRIB on "
 				 "file %s - %s\n", smb_fname_str_dbg(smb_fname),
 				 attrstr));
-	                return false;
+			/* Should this be INTERNAL_ERROR? */
+	                return NT_STATUS_INVALID_PARAMETER;
 	}
 
 	if (S_ISDIR(smb_fname->st.st_ex_mode)) {
@@ -363,7 +364,7 @@ static bool get_ea_dos_attribute(connection_struct *conn,
 
 	dos_mode_debug_print(__func__, *pattr);
 
-	return True;
+	return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -371,14 +372,18 @@ static bool get_ea_dos_attribute(connection_struct *conn,
  Also sets the create time.
 ****************************************************************************/
 
-static bool set_ea_dos_attribute(connection_struct *conn,
-				 struct smb_filename *smb_fname,
-				 uint32_t dosmode)
+NTSTATUS set_ea_dos_attribute(connection_struct *conn,
+			      const struct smb_filename *smb_fname,
+			      uint32_t dosmode)
 {
 	struct xattr_DOSATTRIB dosattrib;
 	enum ndr_err_code ndr_err;
 	DATA_BLOB blob;
 
+	if (!lp_store_dos_attributes(SNUM(conn))) {
+		return NT_STATUS_NOT_IMPLEMENTED;
+	}
+
 	ZERO_STRUCT(dosattrib);
 	ZERO_STRUCT(blob);
 
@@ -401,17 +406,18 @@ static bool set_ea_dos_attribute(connection_struct *conn,
 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 		DEBUG(5, ("create_acl_blob: ndr_push_xattr_DOSATTRIB failed: %s\n",
 			ndr_errstr(ndr_err)));
-		return false;
+		return ndr_map_error2ntstatus(ndr_err);
 	}
 
 	if (blob.data == NULL || blob.length == 0) {
-		return false;
+		/* Should this be INTERNAL_ERROR? */
+		return NT_STATUS_INVALID_PARAMETER;
 	}
 
 	if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
 			     SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length,
 			     0) == -1) {
-		bool ret = false;
+		NTSTATUS status = NT_STATUS_OK;
 		bool need_close = false;
 		files_struct *fsp = NULL;
 
@@ -419,7 +425,7 @@ static bool set_ea_dos_attribute(connection_struct *conn,
 			DBG_INFO("Cannot set "
 				 "attribute EA on file %s: Error = %s\n",
 				 smb_fname_str_dbg(smb_fname), strerror(errno));
-			return false;
+			return map_nt_error_from_unix(errno);
 		}
 
 		/* We want DOS semantics, ie allow non owner with write permission to change the
@@ -428,10 +434,10 @@ static bool set_ea_dos_attribute(connection_struct *conn,
 
 		/* Check if we have write access. */
 		if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
-			return false;
+			return NT_STATUS_ACCESS_DENIED;
 
 		if (!can_write_to_file(conn, smb_fname)) {
-			return false;
+			return NT_STATUS_ACCESS_DENIED;
 		}
 
 		/*
@@ -439,29 +445,30 @@ static bool set_ea_dos_attribute(connection_struct *conn,
 		 * metadata operation under root.
 		 */
 
-		if (!NT_STATUS_IS_OK(get_file_handle_for_metadata(conn,
+		status = get_file_handle_for_metadata(conn,
 						smb_fname,
 						&fsp,
-						&need_close))) {
-			return false;
+						&need_close);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
 		}
 
 		become_root();
 		if (SMB_VFS_FSETXATTR(fsp,
 				     SAMBA_XATTR_DOS_ATTRIB, blob.data,
 				     blob.length, 0) == 0) {
-			ret = true;
+			status = NT_STATUS_OK;
 		}
 		unbecome_root();
 		if (need_close) {
 			close_file(NULL, fsp, NORMAL_CLOSE);
 		}
-		return ret;
+		return status;
 	}
 	DEBUG(10,("set_ea_dos_attribute: set EA 0x%x on file %s\n",
 		(unsigned int)dosmode,
 		smb_fname_str_dbg(smb_fname)));
-	return true;
+	return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -565,6 +572,7 @@ uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
 {
 	uint32_t result = 0;
 	bool offline;
+	NTSTATUS status = NT_STATUS_OK;
 
 	DEBUG(8,("dos_mode: %s\n", smb_fname_str_dbg(smb_fname)));
 
@@ -589,8 +597,9 @@ uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
 		}
 	}
 
-	/* Get the DOS attributes from an EA by preference. */
-	if (!get_ea_dos_attribute(conn, smb_fname, &result)) {
+	/* Get the DOS attributes via the VFS if we can */
+	status = SMB_VFS_GET_DOS_ATTRIBUTES(conn, smb_fname, &result);
+	if (!NT_STATUS_IS_OK(status)) {
 		result |= dos_mode_from_sbuf(conn, smb_fname);
 	}
 
@@ -601,8 +610,8 @@ uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
 
 	if (conn->fs_capabilities & FILE_FILE_COMPRESSION) {
 		bool compressed = false;
-		NTSTATUS status = dos_mode_check_compressed(conn, smb_fname,
-							    &compressed);
+		status = dos_mode_check_compressed(conn, smb_fname,
+						   &compressed);
 		if (NT_STATUS_IS_OK(status) && compressed) {
 			result |= FILE_ATTRIBUTE_COMPRESSED;
 		}
@@ -696,23 +705,27 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
 	smb_fname->st.st_ex_btime = new_create_timespec;
 
 	/* Store the DOS attributes in an EA by preference. */
-	if (lp_store_dos_attributes(SNUM(conn))) {
-		/*
-		 * Don't fall back to using UNIX modes. Finally
-		 * follow the smb.conf manpage.
-		 */
-		if (!set_ea_dos_attribute(conn, smb_fname, dosmode)) {
-			return -1;
-		}
+	status = SMB_VFS_SET_DOS_ATTRIBUTES(conn, smb_fname, dosmode);
+	if (NT_STATUS_IS_OK(status)) {
 		if (!newfile) {
 			notify_fname(conn, NOTIFY_ACTION_MODIFIED,
-				     FILE_NOTIFY_CHANGE_ATTRIBUTES,
-				     smb_fname->base_name);
+				FILE_NOTIFY_CHANGE_ATTRIBUTES,
+				smb_fname->base_name);
 		}
 		smb_fname->st.st_ex_mode = unixmode;
 		return 0;
+	} else {
+		/*
+		 * Only fall back to using UNIX modes if
+		 * we get NOT_IMPLEMENTED.
+		 */
+		if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
+			errno = map_errno_from_nt_status(status);
+			return -1;
+		}
 	}
 
+	/* Fall back to UNIX modes. */
 	unixmode = unix_mode(conn, dosmode, smb_fname, parent_dir);
 
 	/* preserve the file type bits */
@@ -896,12 +909,9 @@ NTSTATUS file_set_sparse(connection_struct *conn,
 	}
 
 	/* Store the DOS attributes in an EA. */
-	if (!set_ea_dos_attribute(conn, fsp->fsp_name,
-				  new_dosmode)) {
-		if (errno == 0) {
-			errno = EIO;
-		}
-		return map_nt_error_from_unix(errno);
+	status = SMB_VFS_FSET_DOS_ATTRIBUTES(conn, fsp, new_dosmode);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
 	}
 
 	notify_fname(conn, NOTIFY_ACTION_MODIFIED,
@@ -1080,13 +1090,14 @@ struct timespec get_change_timespec(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS get_file_handle_for_metadata(connection_struct *conn,
-				struct smb_filename *smb_fname,
+				const struct smb_filename *smb_fname,
 				files_struct **ret_fsp,
 				bool *need_close)
 {
 	NTSTATUS status;
 	files_struct *fsp;
 	struct file_id file_id;
+	struct smb_filename *smb_fname_cp = NULL;
 
 	*need_close = false;
 
@@ -1105,12 +1116,18 @@ static NTSTATUS get_file_handle_for_metadata(connection_struct *conn,
 		}
 	}
 
+	smb_fname_cp = cp_smb_filename(talloc_tos(),
+					smb_fname);
+	if (smb_fname_cp == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	/* Opens an INTERNAL_OPEN_ONLY write handle. */
 	status = SMB_VFS_CREATE_FILE(
 		conn,                                   /* conn */
 		NULL,                                   /* req */
 		0,                                      /* root_dir_fid */
-		smb_fname,                              /* fname */
+		smb_fname_cp,				/* fname */
 		FILE_WRITE_DATA,                        /* access_mask */
 		(FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
 			FILE_SHARE_DELETE),
@@ -1127,6 +1144,8 @@ static NTSTATUS get_file_handle_for_metadata(connection_struct *conn,
 		NULL,                                   /* pinfo */
 		NULL, NULL);				/* create context */
 
+	TALLOC_FREE(smb_fname_cp);
+
 	if (NT_STATUS_IS_OK(status)) {
 		*need_close = true;
 	}
-- 
2.8.0.rc3.226.g39d4020



More information about the samba-technical mailing list