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() */

Reply via email to