[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Thu Aug 8 01:06:02 UTC 2019


The branch, master has been updated
       via  897c36f2cb7 torture: SMB1 unlink needs delay for a stream's SHARING_VIOLATION
       via  4c08043ee54 smbd: Move handling the 1sec sharing_violation delay into smb1 code
       via  c7e110e51af smbd: Add defer_sharing_violation_smb1
       via  305ea37c81c smbd: Get "req->request_time" early in create_file_default()
       via  1bc7d18b5f9 smbd: Do not exceed the req's max timeout in setup_poll_open()
       via  50a3d08673a smbd: Make setup_poll_open() return bool
       via  832b9eb6df5 smbd: Make setup_kernel_oplock_poll_open() more general
       via  939a1097504 smbd: Avoid exit_server() in setup_kernel_oplock_poll_open()
       via  2c653515f39 smbd: Remove access check on SHARING_VIOLATION
      from  551e3590f98 s3: VFS: Make setxattr return errno = EROFS on a shadow copy path.

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 897c36f2cb7de561394ab15e8134fb6e5b91ae63
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Aug 1 14:47:41 2019 +0200

    torture: SMB1 unlink needs delay for a stream's SHARING_VIOLATION
    
    Survives against W2k12R2
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Thu Aug  8 01:05:38 UTC 2019 on sn-devel-184

commit 4c08043ee54350c7c66a963882d4e14c24472986
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jul 30 14:54:40 2019 +0200

    smbd: Move handling the 1sec sharing_violation delay into smb1 code
    
    Simplify the flow in open_file_ntcreate, streamline it for SMB2
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit c7e110e51afea9a36a060bff62506c53e86c8aab
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jul 30 14:54:18 2019 +0200

    smbd: Add defer_sharing_violation_smb1
    
    This is close to what Windows SMB1 does: Instead of waiting for the
    share entry causing the SHARING_VIOLATION to disappear, retry every
    200msec up to one second. Windows does it a little differently: Retry
    up to 5 times. But up to one second should be close enough.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 305ea37c81c2eeafb0ae259d4bd319af183a4611
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Aug 2 11:54:11 2019 +0200

    smbd: Get "req->request_time" early in create_file_default()
    
    This is necessary for the following case:
    
    We want to delete a file with an open stream that is not open with
    FILE_SHARE_DELETE. In SMB1, we need to defer the sharing violation
    reply (we don't do that right now, test to follow). However, when we
    move that sharing violation delay to where it belongs, into the outer
    layers, only very deep in the nested open_streams_for_delete smb1
    sharing violation delay handling call we will hit the sharing
    violation in the 1-second retry case. However, that
    open_streams_for_delete itself is INTERNAL_OPEN_ONLY and thus not
    deferred itself. This means that it will not overwrite
    req->request_time at all.
    
    Exec summary: We only have one request_time now, set it properly as
    early as possible.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1bc7d18b5f97d9b7e299df2107321601178aed83
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Aug 2 14:33:22 2019 +0200

    smbd: Do not exceed the req's max timeout in setup_poll_open()
    
    This will become important in the next commits when the SMB1 sharing
    violation delay will use this. We want to be able to reduce the
    timeout to less than 200msec, see the next commits.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 50a3d08673ad5a62ff5769af429e2cc1730a1659
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jul 30 14:51:00 2019 +0200

    smbd: Make setup_poll_open() return bool
    
    This is for callers who don't want to call open_was_deferred()
    afterwards
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 832b9eb6df520b3ba9f60e8559c2bb9bef2b4ad4
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jul 30 14:00:17 2019 +0200

    smbd: Make setup_kernel_oplock_poll_open() more general
    
    This is a generic "open retry without locking.tdb waiter" loop: Take
    the specific timeouts as parameters.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 939a1097504540779343dd53fad6cdec581b0e2c
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Jul 30 13:41:17 2019 +0200

    smbd: Avoid exit_server() in setup_kernel_oplock_poll_open()
    
    Failure to postpone a request is not really fatal: We just don't retry
    as wanted but return an error to the client that might have resolved
    itself after a few seconds. From my point of view such a spurious and
    rare error, which is highly unlikely anyway does not justify to kill
    that client's connection.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 2c653515f39e341d7b104cef75f8109410bc90c7
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Jul 26 12:09:14 2019 +0200

    smbd: Remove access check on SHARING_VIOLATION
    
    This piece of code predates our user-space access checks, which we
    nowadays always do in open_file()
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source3/selftest/tests.py |   1 +
 source3/smbd/nttrans.c    |  18 ++++
 source3/smbd/open.c       | 197 ++++++++++++++++++--------------------
 source3/smbd/proto.h      |   1 +
 source3/smbd/reply.c      |  41 ++++++++
 source3/smbd/trans2.c     |  17 ++++
 source3/torture/torture.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 409 insertions(+), 104 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 4c6264e129f..c1058091410 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -96,6 +96,7 @@ tests = ["FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7"
          "CLEANUP1",
          "CLEANUP2",
          "CLEANUP4",
+         "DELETE-STREAM",
          "BAD-NBT-SESSION"]
 
 for t in tests:
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 38d5b1f428b..a083f352261 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -591,6 +591,12 @@ void reply_ntcreate_and_X(struct smb_request *req)
 			/* We have re-scheduled this call, no error. */
 			goto out;
 		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				goto out;
+			}
+		}
 		reply_openerror(req, status);
 		goto out;
 	}
@@ -1243,6 +1249,12 @@ static void call_nt_transact_create(connection_struct *conn,
 			/* We have re-scheduled this call, no error. */
 			return;
 		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				return;
+			}
+		}
 		reply_openerror(req, status);
 		goto out;
 	}
@@ -1732,6 +1744,12 @@ void reply_ntrename(struct smb_request *req)
 			/* We have re-scheduled this call. */
 			goto out;
 		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				goto out;
+			}
+		}
 
 		reply_nterror(req, status);
 		goto out;
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index c75754d1e16..e33c7874883 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2488,10 +2488,10 @@ static void defer_open_done(struct tevent_req *req)
  * Actually attempt the kernel oplock polling open.
  */
 
-static void kernel_oplock_poll_open_timer(struct tevent_context *ev,
-				      struct tevent_timer *te,
-				      struct timeval current_time,
-				      void *private_data)
+static void poll_open_fn(struct tevent_context *ev,
+			 struct tevent_timer *te,
+			 struct timeval current_time,
+			 void *private_data)
 {
 	struct deferred_open_record *open_rec = talloc_get_type_abort(
 		private_data, struct deferred_open_record);
@@ -2502,50 +2502,99 @@ static void kernel_oplock_poll_open_timer(struct tevent_context *ev,
 	if (!ok) {
 		exit_server("schedule_deferred_open_message_smb failed");
 	}
-	DBG_DEBUG("kernel_oplock_poll_open_timer fired. Retrying open !\n");
+	DBG_DEBUG("timer fired. Retrying open !\n");
 }
 
 /**
  * Reschedule an open for 1 second from now, if not timed out.
  **/
-static void setup_kernel_oplock_poll_open(struct smb_request *req,
-					  struct file_id id)
+static bool setup_poll_open(
+	struct smb_request *req,
+	struct file_id id,
+	struct timeval max_timeout,
+	struct timeval interval)
 {
 
 	bool ok;
 	struct deferred_open_record *open_rec = NULL;
-	/* Maximum wait time. */
-	struct timeval timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
+	struct timeval endtime, next_interval;
 
-	if (request_timed_out(req, timeout)) {
-		return;
+	if (request_timed_out(req, max_timeout)) {
+		return false;
 	}
 
 	open_rec = talloc_zero(NULL, struct deferred_open_record);
 	if (open_rec == NULL) {
-		exit_server("talloc failed");
+		DBG_WARNING("talloc failed\n");
+		return false;
 	}
 	open_rec->xconn = req->xconn;
 	open_rec->mid = req->mid;
 
-	ok = push_deferred_open_message_smb(req, timeout, id, open_rec);
-	if (!ok) {
-		exit_server("push_deferred_open_message_smb failed");
-	}
+	/*
+	 * Make sure open_rec->te does not come later than the
+	 * request's maximum endtime.
+	 */
 
-	open_rec->te = tevent_add_timer(req->sconn->ev_ctx,
-					open_rec,
-					timeval_current_ofs(1, 0),
-					kernel_oplock_poll_open_timer,
-					open_rec);
+	endtime = timeval_sum(&req->request_time, &max_timeout);
+	next_interval = timeval_current_ofs(interval.tv_sec, interval.tv_usec);
+	next_interval = timeval_min(&endtime, &next_interval);
+
+	open_rec->te = tevent_add_timer(
+		req->sconn->ev_ctx,
+		open_rec,
+		next_interval,
+		poll_open_fn,
+		open_rec);
 	if (open_rec->te == NULL) {
-		exit_server("tevent_add_timer failed");
+		DBG_WARNING("tevent_add_timer failed\n");
+		TALLOC_FREE(open_rec);
+		return false;
+	}
+
+	ok = push_deferred_open_message_smb(req, max_timeout, id, open_rec);
+	if (!ok) {
+		DBG_WARNING("push_deferred_open_message_smb failed\n");
+		TALLOC_FREE(open_rec);
+		return false;
 	}
 
 	DBG_DEBUG("poll request time [%s] mid [%" PRIu64 "] file_id [%s]\n",
 		  timeval_string(talloc_tos(), &req->request_time, false),
 		  req->mid,
 		  file_id_string_tos(&id));
+
+	return true;
+}
+
+bool defer_smb1_sharing_violation(struct smb_request *req)
+{
+	bool ok;
+	int timeout_usecs;
+
+	if (!lp_defer_sharing_violations()) {
+		return false;
+	}
+
+	/*
+	 * Try every 200msec up to (by default) one second. To be
+	 * precise, according to behaviour note <247> in [MS-CIFS],
+	 * the server tries 5 times. But up to one second should be
+	 * close enough.
+	 */
+
+	timeout_usecs = lp_parm_int(
+		SNUM(req->conn),
+		"smbd",
+		"sharedelay",
+		SHARING_VIOLATION_USEC_WAIT);
+
+	ok = setup_poll_open(
+		req,
+		(struct file_id) {0},
+		(struct timeval) { .tv_usec = timeout_usecs },
+		(struct timeval) { .tv_usec = 200000 });
+	return ok;
 }
 
 /****************************************************************************
@@ -3011,15 +3060,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 
 	if (req) {
 		struct deferred_open_record *open_rec;
-		struct timeval request_time;
-		if (get_deferred_open_message_state(req,
-				&request_time,
-				&open_rec)) {
-			/* Remember the absolute time of the original
-			   request with this mid. We'll use it later to
-			   see if this has timed out. */
-
-			req->request_time = request_time;
+		if (get_deferred_open_message_state(req, NULL, &open_rec)) {
 
 			/* If it was an async create retry, the file
 			   didn't exist. */
@@ -3299,7 +3340,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 			 * second to retry a non-blocking open until the time
 			 * expires.
 			 */
-			setup_kernel_oplock_poll_open(req, fsp->file_id);
+			setup_poll_open(
+				req,
+				fsp->file_id,
+				timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0),
+				timeval_set(1, 0));
 			DBG_DEBUG("No Samba oplock around after EWOULDBLOCK. "
 				"Retrying with poll\n");
 			return NT_STATUS_SHARING_VIOLATION;
@@ -3325,7 +3370,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 		 * second to retry a non-blocking open until the time
 		 * expires.
 		 */
-		setup_kernel_oplock_poll_open(req, fsp->file_id);
+		setup_poll_open(
+			req,
+			fsp->file_id,
+			timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0),
+			timeval_set(1, 0));
 
 		TALLOC_FREE(lck);
 		DBG_DEBUG("No Samba oplock around after EWOULDBLOCK. "
@@ -3454,82 +3503,13 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 	}
 
 	if (!NT_STATUS_IS_OK(status)) {
-		uint32_t can_access_mask;
-		bool can_access = True;
 
 		SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION));
 
-		/*
-		 * This next line is a subtlety we need for
-		 * MS-Access. If a file open will fail due to share
-		 * permissions and also for security (access) reasons,
-		 * we need to return the access failed error, not the
-		 * share error. We can't open the file due to kernel
-		 * oplock deadlock (it's possible we failed above on
-		 * the open_mode_check()) so use a userspace check.
-		 */
-
-		if (flags & O_RDWR) {
-			can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
-		} else if (flags & O_WRONLY) {
-			can_access_mask = FILE_WRITE_DATA;
-		} else {
-			can_access_mask = FILE_READ_DATA;
-		}
-
-		if (((can_access_mask & FILE_WRITE_DATA) &&
-		     !CAN_WRITE(conn)) ||
-		    !NT_STATUS_IS_OK(smbd_check_access_rights(conn,
-							      smb_fname,
-							      false,
-							      can_access_mask))) {
-			can_access = False;
-		}
-
-		/*
-		 * If we're returning a share violation, ensure we
-		 * cope with the braindead 1 second delay (SMB1 only).
-		 */
-
-		if (!(oplock_request & INTERNAL_OPEN_ONLY) &&
-		    !conn->sconn->using_smb2 &&
-		    lp_defer_sharing_violations()) {
-			struct timeval timeout;
-			int timeout_usecs;
-
-			/* this is a hack to speed up torture tests
-			   in 'make test' */
-			timeout_usecs = lp_parm_int(SNUM(conn),
-						    "smbd","sharedelay",
-						    SHARING_VIOLATION_USEC_WAIT);
-
-			/* This is a relative time, added to the absolute
-			   request_time value to get the absolute timeout time.
-			   Note that if this is the second or greater time we enter
-			   this codepath for this particular request mid then
-			   request_time is left as the absolute time of the *first*
-			   time this request mid was processed. This is what allows
-			   the request to eventually time out. */
-
-			timeout = timeval_set(0, timeout_usecs);
-
-			if (!request_timed_out(req, timeout)) {
-				defer_open(lck, timeout, req, false, id);
-			}
-		}
-
 		TALLOC_FREE(lck);
 		fd_close(fsp);
-		if (can_access) {
-			/*
-			 * We have detected a sharing violation here
-			 * so return the correct error code
-			 */
-			status = NT_STATUS_SHARING_VIOLATION;
-		} else {
-			status = NT_STATUS_ACCESS_DENIED;
-		}
-		return status;
+
+		return NT_STATUS_SHARING_VIOLATION;
 	}
 
 	/* Should we atomically (to the client at least) truncate ? */
@@ -5562,6 +5542,15 @@ NTSTATUS create_file_default(connection_struct *conn,
 		  (unsigned int)root_dir_fid,
 		  ea_list, sd, smb_fname_str_dbg(smb_fname));
 
+	if (req != NULL) {
+		/*
+		 * Remember the absolute time of the original request
+		 * with this mid. We'll use it later to see if this
+		 * has timed out.
+		 */
+		get_deferred_open_message_state(req, &req->request_time, NULL);
+	}
+
 	/*
 	 * Calculate the filename from the root_dir_if if necessary.
 	 */
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 6d3a10f9d75..0fde9b78fb0 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -680,6 +680,7 @@ NTSTATUS send_break_message(struct messaging_context *msg_ctx,
 			    uint16_t break_to);
 struct deferred_open_record;
 bool is_deferred_open_async(const struct deferred_open_record *rec);
+bool defer_smb1_sharing_violation(struct smb_request *req);
 NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
 			  struct smb_filename *smb_dname);
 void msg_file_was_renamed(struct messaging_context *msg,
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 946acb130d5..5664090f38c 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2308,6 +2308,10 @@ void reply_open(struct smb_request *req)
 			create_options,
 			private_flags);
 		if (fsp == NULL) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				goto out;
+			}
 			reply_openerror(req, status);
 			goto out;
 		}
@@ -2495,9 +2499,15 @@ void reply_open_and_X(struct smb_request *req)
 			create_options,
 			private_flags);
 		if (fsp == NULL) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				goto out;
+			}
 			reply_openerror(req, status);
 			goto out;
 		}
+
+
 		smb_action = FILE_WAS_OPENED;
 	}
 
@@ -2748,6 +2758,12 @@ void reply_mknew(struct smb_request *req)
 			/* We have re-scheduled this call. */
 			goto out;
 		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				goto out;
+			}
+		}
 		reply_openerror(req, status);
 		goto out;
 	}
@@ -2885,6 +2901,13 @@ void reply_ctemp(struct smb_request *req)
 				/* We have re-scheduled this call. */
 				goto out;
 			}
+			if (NT_STATUS_EQUAL(
+				    status, NT_STATUS_SHARING_VIOLATION)) {
+				bool ok = defer_smb1_sharing_violation(req);
+				if (ok) {
+					goto out;
+				}
+			}
 			reply_openerror(req, status);
 			goto out;
 		}
@@ -3402,6 +3425,12 @@ void reply_unlink(struct smb_request *req)
 			/* We have re-scheduled this call. */
 			goto out;
 		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				goto out;
+			}
+		}
 		reply_nterror(req, status);
 		goto out;
 	}
@@ -6545,6 +6574,12 @@ void reply_rmdir(struct smb_request *req)
 			/* We have re-scheduled this call. */
 			goto out;
 		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				goto out;
+			}
+		}
 		reply_nterror(req, status);
 		goto out;
 	}
@@ -7678,6 +7713,12 @@ void reply_mv(struct smb_request *req)
 			/* We have re-scheduled this call. */
 			goto out;
 		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				goto out;
+			}
+		}
 		reply_nterror(req, status);
 		goto out;
 	}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 73515062729..d268558cfb8 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1454,9 +1454,14 @@ static void call_trans2open(connection_struct *conn,
 			create_options,
 			private_flags);
 		if (fsp == NULL) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				goto out;
+			}
 			reply_openerror(req, status);
 			goto out;
 		}
+
 		smb_action = FILE_WAS_OPENED;
 	}
 
@@ -6370,6 +6375,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 			/* We have re-scheduled this call. */
 			return;
 		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				return;
+			}
+		}
 		reply_nterror(req, status);
 		return;
 	}
@@ -9322,6 +9333,12 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
 			/* We have re-scheduled this call. */
 			return;
 		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+			bool ok = defer_smb1_sharing_violation(req);
+			if (ok) {
+				return;
+			}
+		}
 		if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
 			/* We have re-scheduled this call. */
 			return;
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 2779e8e3aa8..7ead71c644d 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -5643,6 +5643,240 @@ static bool run_deletetest(int dummy)
 	return correct;
 }
 
+struct delete_stream_state {
+	bool closed;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list