[PATCH] Fix bug 10260 - smbclient shows no error if deleting a directory with del failed

Jeremy Allison jra at samba.org
Thu Nov 14 11:18:00 MST 2013


On Thu, Nov 14, 2013 at 09:18:53AM +0100, Andreas Schneider wrote:
> On Wednesday 13 November 2013 13:12:03 Jeremy Allison wrote:
> > Please review and/or push.
> 
> Hi Jeremy,
> 
> could you please use the commit comment style for bugs we agreed too?

Updated. Please review. Thanks !

Jeremy.
-------------- next part --------------
From 91a09b0f07a1c76385c511634e1cff0396d11244 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 12 Nov 2013 15:17:26 -0800
Subject: [PATCH 1/3] s3-smbd: smbclient shows no error if deleting a directory with del failed

BUG: https://bugzilla.samba.org/show_bug.cgi?id=10260

Remove unneeded conn argument to dir_check_ftype().
Move to correct uint32_t types.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/dir.c   | 6 +++---
 source3/smbd/proto.h | 2 +-
 source3/smbd/reply.c | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index d99eec2..6b7cce2 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -966,9 +966,9 @@ struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
  Check that a file matches a particular file type.
 ****************************************************************************/
 
-bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
+bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
 {
-	uint32 mask;
+	uint32_t mask;
 
 	/* Check the "may have" search bits. */
 	if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0)
@@ -1106,7 +1106,7 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
 			continue;
 		}
 
-		if (!dir_check_ftype(conn, mode, dirtype)) {
+		if (!dir_check_ftype(mode, dirtype)) {
 			DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
 				fname, (unsigned int)mode, (unsigned int)dirtype));
 			TALLOC_FREE(dname);
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index a15d520..a373cd6 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -218,7 +218,7 @@ struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
 			       char *buf,int *num);
 struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
 				       int dptr_num);
-bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype);
+bool dir_check_ftype(uint32_t mode, uint32_t dirtype);
 bool get_dir_entry(TALLOC_CTX *ctx,
 		struct dptr_struct *dirptr,
 		const char *mask,
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 3f59df8..b160290 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2655,7 +2655,7 @@ static NTSTATUS do_unlink(connection_struct *conn,
 		return NT_STATUS_NO_SUCH_FILE;
 	}
 
-	if (!dir_check_ftype(conn, fattr, dirtype)) {
+	if (!dir_check_ftype(fattr, dirtype)) {
 		if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
 			return NT_STATUS_FILE_IS_A_DIRECTORY;
 		}
-- 
1.8.4.1


From 83b067a97065ee6d8df7e9b09394218d7115acf5 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 12 Nov 2013 15:32:42 -0800
Subject: [PATCH 2/3] s3-lib: smbclient shows no error if deleting a directory with del failed

BUG: https://bugzilla.samba.org/show_bug.cgi?id=10260

Move dir_check_ftype() to util.c

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/include/proto.h |  1 +
 source3/lib/util.c      | 42 ++++++++++++++++++++++++++++++++++++++++++
 source3/smbd/dir.c      | 26 --------------------------
 source3/smbd/proto.h    |  1 -
 4 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 277547b..fc7f24d 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -475,6 +475,7 @@ bool map_open_params_to_ntcreate(const char *smb_base_fname,
 				 uint32 *pcreate_options,
 				 uint32_t *pprivate_flags);
 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok);
+bool dir_check_ftype(uint32_t mode, uint32_t dirtype);
 void init_modules(void);
 
 /* The following definitions come from lib/util_builtin.c  */
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 5168092..551beab 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -2393,3 +2393,45 @@ struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct securi
 	}
 	return cpy;
 }
+
+/****************************************************************************
+ Check that a file matches a particular file type.
+****************************************************************************/
+
+bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
+{
+	uint32_t mask;
+
+	/* Check the "may have" search bits. */
+	if (((mode & ~dirtype) &
+			(FILE_ATTRIBUTE_HIDDEN |
+			 FILE_ATTRIBUTE_SYSTEM |
+			 FILE_ATTRIBUTE_DIRECTORY)) != 0) {
+		return false;
+	}
+
+	/* Check the "must have" bits,
+	   which are the may have bits shifted eight */
+	/* If must have bit is set, the file/dir can
+	   not be returned in search unless the matching
+	   file attribute is set */
+	mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
+				    FILE_ATTRIBUTE_ARCHIVE|
+				   FILE_ATTRIBUTE_READONLY|
+				     FILE_ATTRIBUTE_HIDDEN|
+				     FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
+	if(mask) {
+		if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
+				      FILE_ATTRIBUTE_ARCHIVE|
+				     FILE_ATTRIBUTE_READONLY|
+				       FILE_ATTRIBUTE_HIDDEN|
+					FILE_ATTRIBUTE_SYSTEM))) == mask) {
+			/* check if matching attribute present */
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	return true;
+}
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 6b7cce2..8fa320b 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -962,32 +962,6 @@ struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
 	return(dptr);
 }
 
-/****************************************************************************
- Check that a file matches a particular file type.
-****************************************************************************/
-
-bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
-{
-	uint32_t mask;
-
-	/* Check the "may have" search bits. */
-	if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0)
-		return False;
-
-	/* Check the "must have" bits, which are the may have bits shifted eight */
-	/* If must have bit is set, the file/dir can not be returned in search unless the matching
-		file attribute is set */
-	mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
-	if(mask) {
-		if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) == mask)   /* check if matching attribute present */
-			return True;
-		else
-			return False;
-	}
-
-	return True;
-}
-
 static bool mangle_mask_match(connection_struct *conn,
 		const char *filename,
 		const char *mask)
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index a373cd6..a550dd7 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -218,7 +218,6 @@ struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
 			       char *buf,int *num);
 struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
 				       int dptr_num);
-bool dir_check_ftype(uint32_t mode, uint32_t dirtype);
 bool get_dir_entry(TALLOC_CTX *ctx,
 		struct dptr_struct *dirptr,
 		const char *mask,
-- 
1.8.4.1


From b5e0610f51b4155c8b3da854d718ccffb59ac9da Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 12 Nov 2013 15:55:51 -0800
Subject: [PATCH 3/3] s3-client: smbclient shows no error if deleting a directory with del failed

BUG: https://bugzilla.samba.org/show_bug.cgi?id=10260

In SMB1 the server filters by attribute requested, in SMB2 there is
no attribute sent. Emulate this on the client to provide the same
ABI to callers.

In SMB1 the server returns NT_STATUS_NO_SUCH_FILE if FindFirst
finds no files. Emulate this on the client.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/libsmb/cli_smb2_fnum.c | 29 ++++++++++++++++++++++++++---
 source3/libsmb/cli_smb2_fnum.h |  1 +
 source3/libsmb/clilist.c       |  2 +-
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
index 202000f..d10e1d2 100644
--- a/source3/libsmb/cli_smb2_fnum.c
+++ b/source3/libsmb/cli_smb2_fnum.c
@@ -486,6 +486,7 @@ static bool windows_parent_dirname(TALLOC_CTX *mem_ctx,
 
 NTSTATUS cli_smb2_list(struct cli_state *cli,
 			const char *pathname,
+			uint16_t attribute,
 			NTSTATUS (*fn)(const char *,
 				struct file_info *,
 				const char *,
@@ -497,6 +498,7 @@ NTSTATUS cli_smb2_list(struct cli_state *cli,
 	char *parent_dir = NULL;
 	const char *mask = NULL;
 	struct smb2_hnd *ph = NULL;
+	bool processed_file = false;
 	TALLOC_CTX *frame = talloc_stackframe();
 	TALLOC_CTX *subframe = NULL;
 
@@ -590,13 +592,26 @@ NTSTATUS cli_smb2_list(struct cli_state *cli,
 				goto fail;
 			}
 
-			status = fn(cli->dfs_mountpoint,
+			if (dir_check_ftype((uint32_t)finfo->mode,
+					(uint32_t)attribute)) {
+				/*
+				 * Only process if attributes match.
+				 * On SMB1 server does this, so on
+				 * SMB2 we need to emulate in the
+				 * client.
+				 *
+				 * https://bugzilla.samba.org/show_bug.cgi?id=10260
+				 */
+				processed_file = true;
+
+				status = fn(cli->dfs_mountpoint,
 					finfo,
 					pathname,
 					state);
 
-			if (!NT_STATUS_IS_OK(status)) {
-				break;
+				if (!NT_STATUS_IS_OK(status)) {
+					break;
+				}
 			}
 
 			TALLOC_FREE(finfo);
@@ -616,6 +631,14 @@ NTSTATUS cli_smb2_list(struct cli_state *cli,
 		status = NT_STATUS_OK;
 	}
 
+	if (NT_STATUS_IS_OK(status) && !processed_file) {
+		/*
+		 * In SMB1 findfirst returns NT_STATUS_NO_SUCH_FILE
+		 * if no files match. Emulate this in the client.
+		 */
+		status = NT_STATUS_NO_SUCH_FILE;
+	}
+
   fail:
 
 	if (fnum != 0xffff) {
diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h
index 0068686..a5cae25 100644
--- a/source3/libsmb/cli_smb2_fnum.h
+++ b/source3/libsmb/cli_smb2_fnum.h
@@ -42,6 +42,7 @@ NTSTATUS cli_smb2_rmdir(struct cli_state *cli, const char *dirname);
 NTSTATUS cli_smb2_unlink(struct cli_state *cli,const char *fname);
 NTSTATUS cli_smb2_list(struct cli_state *cli,
 			const char *pathname,
+			uint16_t attribute,
 			NTSTATUS (*fn)(const char *,
 				struct file_info *,
 				const char *,
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index ed970cd..3080fb8 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -942,7 +942,7 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16 attribute,
 	uint16_t info_level;
 
 	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
-		return cli_smb2_list(cli, mask, fn, state);
+		return cli_smb2_list(cli, mask, attribute, fn, state);
 	}
 
 	frame = talloc_stackframe();
-- 
1.8.4.1



More information about the samba-technical mailing list