svn commit: samba r16876 - in branches/SAMBA_4_0/source/ntvfs/posix: .

metze at samba.org metze at samba.org
Sat Jul 8 12:35:37 GMT 2006


Author: metze
Date: 2006-07-08 12:35:37 +0000 (Sat, 08 Jul 2006)
New Revision: 16876

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=16876

Log:
implement SMB2 Find in the posix ntvfs backend

metze
Modified:
   branches/SAMBA_4_0/source/ntvfs/posix/pvfs_open.c
   branches/SAMBA_4_0/source/ntvfs/posix/pvfs_search.c
   branches/SAMBA_4_0/source/ntvfs/posix/vfs_posix.h


Changeset:
Modified: branches/SAMBA_4_0/source/ntvfs/posix/pvfs_open.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/posix/pvfs_open.c	2006-07-08 12:34:31 UTC (rev 16875)
+++ branches/SAMBA_4_0/source/ntvfs/posix/pvfs_open.c	2006-07-08 12:35:37 UTC (rev 16876)
@@ -266,6 +266,7 @@
 	f->access_mask   = access_mask;
 	f->brl_handle	 = NULL;
 	f->notify_buffer = NULL;
+	f->search        = NULL;
 
 	f->handle->pvfs              = pvfs;
 	f->handle->name              = talloc_steal(f->handle, name);
@@ -698,6 +699,7 @@
 	f->access_mask       = access_mask;
 	f->impersonation     = io->generic.in.impersonation;
 	f->notify_buffer     = NULL;
+	f->search            = NULL;
 
 	f->handle->pvfs              = pvfs;
 	f->handle->name              = talloc_steal(f->handle, name);
@@ -1126,6 +1128,7 @@
 	f->access_mask   = access_mask;
 	f->impersonation = io->generic.in.impersonation;
 	f->notify_buffer = NULL;
+	f->search        = NULL;
 
 	f->handle->pvfs              = pvfs;
 	f->handle->fd                = -1;

Modified: branches/SAMBA_4_0/source/ntvfs/posix/pvfs_search.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/posix/pvfs_search.c	2006-07-08 12:34:31 UTC (rev 16875)
+++ branches/SAMBA_4_0/source/ntvfs/posix/pvfs_search.c	2006-07-08 12:35:37 UTC (rev 16876)
@@ -58,6 +58,7 @@
 static void pvfs_search_setup_timer(struct pvfs_search_state *search)
 {
 	struct event_context *ev = search->pvfs->ntvfs->ctx->event_ctx;
+	if (search->handle == -1) return;
 	talloc_free(search->te);
 	search->te = event_add_timed(ev, search, 
 				     timeval_current_ofs(search->pvfs->search.inactivity_time, 0), 
@@ -595,6 +596,159 @@
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS pvfs_search_first_smb2(struct ntvfs_module_context *ntvfs,
+				       struct ntvfs_request *req, const struct smb2_find *io, 
+				       void *search_private, 
+				       BOOL (*callback)(void *, union smb_search_data *))
+{
+	struct pvfs_dir *dir;
+	struct pvfs_state *pvfs = ntvfs->private_data;
+	struct pvfs_search_state *search;
+	uint_t reply_count;
+	uint16_t max_count;
+	const char *pattern;
+	NTSTATUS status;
+	struct pvfs_filename *name;
+	struct pvfs_file *f;
+
+	f = pvfs_find_fd(pvfs, req, io->in.file.ntvfs);
+	if (!f) {
+		return NT_STATUS_FILE_CLOSED;
+	}
+
+	/* its only valid for directories */
+	if (f->handle->fd != -1) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (!(f->access_mask & SEC_DIR_LIST)) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	if (f->search) {
+		talloc_free(f->search);
+		f->search = NULL;
+	}
+
+	if (strequal(io->in.pattern, "")) {
+		return NT_STATUS_OBJECT_NAME_INVALID;
+	}
+	if (strchr_m(io->in.pattern, '\\')) {
+		return NT_STATUS_OBJECT_NAME_INVALID;
+	}
+	if (strchr_m(io->in.pattern, '/')) {
+		return NT_STATUS_OBJECT_NAME_INVALID;
+	}
+
+	if (strequal("", f->handle->name->original_name)) {
+		pattern = talloc_asprintf(req, "\\%s", io->in.pattern);
+		NT_STATUS_HAVE_NO_MEMORY(pattern);
+	} else {
+		pattern = talloc_asprintf(req, "\\%s\\%s",
+					  f->handle->name->original_name,
+					  io->in.pattern);
+		NT_STATUS_HAVE_NO_MEMORY(pattern);
+	}
+
+	/* resolve the cifs name to a posix name */
+	status = pvfs_resolve_name(pvfs, req, pattern, PVFS_RESOLVE_WILDCARD, &name);
+	NT_STATUS_NOT_OK_RETURN(status);
+
+	if (!name->has_wildcard && !name->exists) {
+		return NT_STATUS_NO_SUCH_FILE;
+	}
+
+	/* we initially make search a child of the request, then if we
+	   need to keep it long term we steal it for the private
+	   structure */
+	search = talloc(req, struct pvfs_search_state);
+	NT_STATUS_HAVE_NO_MEMORY(search);
+
+	/* do the actual directory listing */
+	status = pvfs_list_start(pvfs, name, search, &dir);
+	NT_STATUS_NOT_OK_RETURN(status);
+
+	search->pvfs		= pvfs;
+	search->handle		= -1;
+	search->dir		= dir;
+	search->current_index	= 0;
+	search->search_attrib	= 0;
+	search->must_attrib	= 0;
+	search->last_used	= 0;
+	search->num_ea_names	= 0;
+	search->ea_names	= NULL;
+	search->te		= NULL;
+
+	if (io->in.continue_flags & SMB2_CONTINUE_FLAG_SINGLE) {
+		max_count = 1;
+	} else {
+		max_count = UINT16_MAX;
+	}
+
+	status = pvfs_search_fill(pvfs, req, max_count, search, io->data_level,
+				  &reply_count, search_private, callback);
+	NT_STATUS_NOT_OK_RETURN(status);
+
+	/* not matching any entries is an error */
+	if (reply_count == 0) {
+		return NT_STATUS_NO_SUCH_FILE;
+	}
+
+	f->search = talloc_steal(f, search);
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS pvfs_search_next_smb2(struct ntvfs_module_context *ntvfs,
+				      struct ntvfs_request *req, const struct smb2_find *io, 
+				      void *search_private, 
+				      BOOL (*callback)(void *, union smb_search_data *))
+{
+	struct pvfs_state *pvfs = ntvfs->private_data;
+	struct pvfs_search_state *search;
+	uint_t reply_count;
+	uint16_t max_count;
+	NTSTATUS status;
+	struct pvfs_file *f;
+
+	f = pvfs_find_fd(pvfs, req, io->in.file.ntvfs);
+	if (!f) {
+		return NT_STATUS_FILE_CLOSED;
+	}
+
+	/* its only valid for directories */
+	if (f->handle->fd != -1) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	/* if there's no search started on the dir handle, it's like a search_first */
+	search = f->search;
+	if (!search) {
+		return pvfs_search_first_smb2(ntvfs, req, io, search_private, callback);
+	}
+
+	if (io->in.continue_flags & SMB2_CONTINUE_FLAG_RESTART) {
+		search->current_index = 0;
+	}
+
+	if (io->in.continue_flags & SMB2_CONTINUE_FLAG_SINGLE) {
+		max_count = 1;
+	} else {
+		max_count = UINT16_MAX;
+	}
+
+	status = pvfs_search_fill(pvfs, req, max_count, search, io->data_level,
+				  &reply_count, search_private, callback);
+	NT_STATUS_NOT_OK_RETURN(status);
+
+	/* not matching any entries is an error */
+	if (reply_count == 0) {
+		return STATUS_NO_MORE_FILES;
+	}
+
+	return NT_STATUS_OK;
+}
+
 /* 
    list files in a directory matching a wildcard pattern
 */
@@ -611,6 +765,9 @@
 
 	case RAW_SEARCH_TRANS2:
 		return pvfs_search_first_trans2(ntvfs, req, io, search_private, callback);
+
+	case RAW_SEARCH_SMB2:
+		return pvfs_search_first_smb2(ntvfs, req, &io->smb2, search_private, callback);
 	}
 
 	return NT_STATUS_INVALID_LEVEL;
@@ -632,6 +789,9 @@
 
 	case RAW_SEARCH_TRANS2:
 		return pvfs_search_next_trans2(ntvfs, req, io, search_private, callback);
+
+	case RAW_SEARCH_SMB2:
+		return pvfs_search_next_smb2(ntvfs, req, &io->smb2, search_private, callback);
 	}
 
 	return NT_STATUS_INVALID_LEVEL;

Modified: branches/SAMBA_4_0/source/ntvfs/posix/vfs_posix.h
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/posix/vfs_posix.h	2006-07-08 12:34:31 UTC (rev 16875)
+++ branches/SAMBA_4_0/source/ntvfs/posix/vfs_posix.h	2006-07-08 12:35:37 UTC (rev 16876)
@@ -181,6 +181,9 @@
 
 	/* for directories, a buffer of pending notify events */
 	struct pvfs_notify_buffer *notify_buffer;
+
+	/* for directories, the state of an incomplete SMB2 Find */
+	struct pvfs_search_state *search;
 };
 
 /* the state of a search started with pvfs_search_first() */



More information about the samba-cvs mailing list