r2520: - finished implementing the server side of the old style search requests
authorAndrew Tridgell <tridge@samba.org>
Wed, 22 Sep 2004 12:38:19 +0000 (12:38 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:59:01 +0000 (12:59 -0500)
(This used to be commit 4e4859c06b9de5fe60ebd17cfb09eed480b79ec1)

source4/include/smb_interfaces.h
source4/libcli/util/errormap.c
source4/ntvfs/posix/pvfs_search.c
source4/smb_server/search.c
source4/torture/raw/search.c

index 72ca1477dcae81ea97c77a079519a1811e44917f..4acdf51b56409a34ffe6719e2199bcfcc4d16342 100644 (file)
@@ -1801,7 +1801,7 @@ union smb_search_data {
                time_t write_time;
                uint32_t size;
                struct smb_search_id id;
-               char *name;
+               const char *name;
        } search;
        
        /* trans2 findfirst RAW_SEARCH_STANDARD level */
index e2aeded65da92fb797d20fd2d6a6218b6fdb9be6..482743b03b845d3f0454f2d2ef47b1b792c4202b 100644 (file)
@@ -50,6 +50,7 @@ static const struct {
        uint32_t dos_code;
        NTSTATUS ntstatus;
 } ntstatus_to_dos_map[] = {
+       {ERRDOS,        ERRnofiles,     STATUS_NO_MORE_FILES},
        {ERRDOS,        ERRgeneral,     NT_STATUS_UNSUCCESSFUL},
        {ERRDOS,        ERRbadfunc,     NT_STATUS_NOT_IMPLEMENTED},
        {ERRDOS,        87,     NT_STATUS_INVALID_INFO_CLASS},
@@ -616,6 +617,7 @@ static const struct {
        uint32_t dos_code;
        NTSTATUS ntstatus;
 } dos_to_ntstatus_map[] = {
+       {ERRDOS,        ERRnofiles,     STATUS_NO_MORE_FILES},
        {ERRDOS,        ERRbadfunc,     NT_STATUS_NOT_IMPLEMENTED},
        {ERRDOS,        ERRbadfile,     NT_STATUS_NO_SUCH_FILE},
        {ERRDOS,        ERRbadpath,     NT_STATUS_OBJECT_PATH_NOT_FOUND},
@@ -628,7 +630,6 @@ static const struct {
        {ERRDOS,        14,     NT_STATUS_SECTION_NOT_EXTENDED},
        {ERRDOS,        ERRremcd,       NT_STATUS_DIRECTORY_NOT_EMPTY},
        {ERRDOS,        ERRdiffdevice,  NT_STATUS_NOT_SAME_DEVICE},
-       {ERRDOS,        ERRnofiles,     NT_STATUS(0x80000006)},
        {ERRDOS,        19,     NT_STATUS_MEDIA_WRITE_PROTECTED},
        {ERRDOS,        21,     NT_STATUS_NO_MEDIA_IN_DEVICE},
        {ERRDOS,        22,     NT_STATUS_INVALID_DEVICE_STATE},
index e51c7477f2ed4d3f851d9f81c00bab02bbe37150..1d1d973d3ffce291644ddda6a1c997b0c1336c18 100644 (file)
 #include "include/includes.h"
 #include "vfs_posix.h"
 
-
-/* 
-   list files in a directory matching a wildcard pattern - old SMBsearch interface
-*/
-static NTSTATUS pvfs_search_first_old(struct smbsrv_request *req, union smb_search_first *io, 
-                                     void *search_private, 
-                                     BOOL (*callback)(void *, union smb_search_data *))
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-/* continue a old style search */
-static NTSTATUS pvfs_search_next_old(struct smbsrv_request *req, union smb_search_next *io, 
-                                    void *search_private, 
-                                    BOOL (*callback)(void *, union smb_search_data *))
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-/* close a old style search */
-static NTSTATUS pvfs_search_close_old(struct smbsrv_request *req, union smb_search_close *io)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 /*
   fill in a single search result for a given info level
 */
@@ -55,7 +30,7 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                                 enum smb_search_level level,
                                 const char *unix_path,
                                 const char *fname, 
-                                uint16_t search_attrib,
+                                struct pvfs_search_state *search,
                                 uint32_t dir_index,
                                 union smb_search_data *file)
 {
@@ -67,13 +42,28 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                return status;
        }
 
-       if (!pvfs_match_attrib(pvfs, name, search_attrib)) {
+       if (!pvfs_match_attrib(pvfs, name, search->search_attrib)) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
        switch (level) {
+       case RAW_SEARCH_SEARCH:
+       case RAW_SEARCH_FFIRST:
+       case RAW_SEARCH_FUNIQUE:
+               file->search.attrib           = name->dos.attrib;
+               file->search.write_time       = nt_time_to_unix(name->dos.write_time);
+               file->search.size             = name->st.st_size;
+               file->search.name             = fname;
+               file->search.id.reserved      = 8;
+               memset(file->search.id.name, ' ', sizeof(file->search.id.name));
+               memcpy(file->search.id.name, fname, MIN(strlen(fname)+1, sizeof(file->search.id.name)));
+               file->search.id.handle        = search->handle;
+               file->search.id.server_cookie = dir_index+1;
+               file->search.id.client_cookie = 0;
+               return NT_STATUS_OK;
+
        case RAW_SEARCH_STANDARD:
-               file->standard.resume_key   = dir_index;
+               file->standard.resume_key   = dir_index+1;
                file->standard.create_time  = nt_time_to_unix(name->dos.create_time);
                file->standard.access_time  = nt_time_to_unix(name->dos.access_time);
                file->standard.write_time   = nt_time_to_unix(name->dos.write_time);
@@ -81,10 +71,10 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                file->standard.alloc_size   = name->dos.alloc_size;
                file->standard.attrib       = name->dos.attrib;
                file->standard.name.s       = fname;
-               break;
+               return NT_STATUS_OK;
 
        case RAW_SEARCH_EA_SIZE:
-               file->ea_size.resume_key   = dir_index;
+               file->ea_size.resume_key   = dir_index+1;
                file->ea_size.create_time  = nt_time_to_unix(name->dos.create_time);
                file->ea_size.access_time  = nt_time_to_unix(name->dos.access_time);
                file->ea_size.write_time   = nt_time_to_unix(name->dos.write_time);
@@ -93,10 +83,10 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                file->ea_size.attrib       = name->dos.attrib;
                file->ea_size.ea_size      = name->dos.ea_size;
                file->ea_size.name.s       = fname;
-               break;
+               return NT_STATUS_OK;
 
        case RAW_SEARCH_DIRECTORY_INFO:
-               file->directory_info.file_index   = dir_index;
+               file->directory_info.file_index   = dir_index+1;
                file->directory_info.create_time  = name->dos.create_time;
                file->directory_info.access_time  = name->dos.access_time;
                file->directory_info.write_time   = name->dos.write_time;
@@ -105,10 +95,10 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                file->directory_info.alloc_size   = name->dos.alloc_size;
                file->directory_info.attrib       = name->dos.attrib;
                file->directory_info.name.s       = fname;
-               break;
+               return NT_STATUS_OK;
 
        case RAW_SEARCH_FULL_DIRECTORY_INFO:
-               file->full_directory_info.file_index   = dir_index;
+               file->full_directory_info.file_index   = dir_index+1;
                file->full_directory_info.create_time  = name->dos.create_time;
                file->full_directory_info.access_time  = name->dos.access_time;
                file->full_directory_info.write_time   = name->dos.write_time;
@@ -118,15 +108,15 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                file->full_directory_info.attrib       = name->dos.attrib;
                file->full_directory_info.ea_size      = name->dos.ea_size;
                file->full_directory_info.name.s       = fname;
-               break;
+               return NT_STATUS_OK;
 
        case RAW_SEARCH_NAME_INFO:
                file->name_info.file_index   = dir_index;
                file->name_info.name.s       = fname;
-               break;
+               return NT_STATUS_OK;
 
        case RAW_SEARCH_BOTH_DIRECTORY_INFO:
-               file->both_directory_info.file_index   = dir_index;
+               file->both_directory_info.file_index   = dir_index+1;
                file->both_directory_info.create_time  = name->dos.create_time;
                file->both_directory_info.access_time  = name->dos.access_time;
                file->both_directory_info.write_time   = name->dos.write_time;
@@ -137,10 +127,10 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                file->both_directory_info.ea_size      = name->dos.ea_size;
                file->both_directory_info.short_name.s = pvfs_short_name(pvfs, name);
                file->both_directory_info.name.s       = fname;
-               break;
+               return NT_STATUS_OK;
 
        case RAW_SEARCH_ID_FULL_DIRECTORY_INFO:
-               file->id_full_directory_info.file_index   = dir_index;
+               file->id_full_directory_info.file_index   = dir_index+1;
                file->id_full_directory_info.create_time  = name->dos.create_time;
                file->id_full_directory_info.access_time  = name->dos.access_time;
                file->id_full_directory_info.write_time   = name->dos.write_time;
@@ -151,10 +141,10 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                file->id_full_directory_info.ea_size      = name->dos.ea_size;
                file->id_full_directory_info.file_id      = name->dos.file_id;
                file->id_full_directory_info.name.s       = fname;
-               break;
+               return NT_STATUS_OK;
 
        case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO:
-               file->id_both_directory_info.file_index   = dir_index;
+               file->id_both_directory_info.file_index   = dir_index+1;
                file->id_both_directory_info.create_time  = name->dos.create_time;
                file->id_both_directory_info.access_time  = name->dos.access_time;
                file->id_both_directory_info.write_time   = name->dos.write_time;
@@ -166,36 +156,13 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                file->id_both_directory_info.file_id      = name->dos.file_id;
                file->id_both_directory_info.short_name.s = pvfs_short_name(pvfs, name);
                file->id_both_directory_info.name.s       = fname;
-               break;
-
-       default:
-               return NT_STATUS_INVALID_LEVEL;
-       }
-
-       return NT_STATUS_OK;
-}
+               return NT_STATUS_OK;
 
-/*
-  return the next available search handle
-*/
-static NTSTATUS pvfs_next_search_handle(struct pvfs_state *pvfs, uint16_t *handle)
-{
-       struct pvfs_search_state *search;
-
-       if (pvfs->search.num_active_searches >= 0x10000) {
-               return NT_STATUS_INSUFFICIENT_RESOURCES;
-       }
-
-       (*handle) = pvfs->search.next_search_handle;
-       for (search=pvfs->search.open_searches;search;search=search->next) {
-               if (*handle == search->handle) {
-                       *handle = ((*handle)+1) & 0xFFFF;
-                       continue;
-               } 
+       case RAW_SEARCH_GENERIC:
+               break;
        }
-       pvfs->search.next_search_handle = ((*handle)+1) & 0xFFFF;
 
-       return NT_STATUS_OK;
+       return NT_STATUS_INVALID_LEVEL;
 }
 
 
@@ -225,7 +192,7 @@ static NTSTATUS pvfs_search_fill(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
                }
 
                status = fill_search_info(pvfs, level, dir->unix_path, dir->names[i], 
-                                         search->search_attrib, i, file);
+                                         search, i, file);
                if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
                        talloc_free(file);
                        continue;
@@ -254,6 +221,156 @@ static NTSTATUS pvfs_search_fill(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
+/*
+  return the next available search handle
+*/
+static NTSTATUS pvfs_next_search_handle(struct pvfs_state *pvfs, uint16_t *handle, 
+                                       uint_t max_handles)
+{
+       struct pvfs_search_state *search;
+
+       if (pvfs->search.num_active_searches >= max_handles) {
+               return NT_STATUS_INSUFFICIENT_RESOURCES;
+       }
+
+       (*handle) = (pvfs->search.next_search_handle) & (max_handles-1);
+again:
+       for (search=pvfs->search.open_searches;search;search=search->next) {
+               if (*handle == search->handle) {
+                       *handle = ((*handle)+1) & (max_handles-1);
+                       goto again;
+               } 
+       }
+       pvfs->search.next_search_handle = ((*handle)+1) & (max_handles-1);
+
+       return NT_STATUS_OK;
+}
+
+
+/* 
+   list files in a directory matching a wildcard pattern - old SMBsearch interface
+*/
+static NTSTATUS pvfs_search_first_old(struct smbsrv_request *req, union smb_search_first *io, 
+                                     void *search_private, 
+                                     BOOL (*callback)(void *, union smb_search_data *))
+{
+       struct pvfs_dir *dir;
+       struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+       struct pvfs_search_state *search;
+       uint_t reply_count;
+       uint16_t search_attrib;
+       const char *pattern;
+       NTSTATUS status;
+       struct pvfs_filename *name;
+
+       search_attrib = io->search_first.in.search_attrib;
+       pattern       = io->search_first.in.pattern;
+
+       /* resolve the cifs name to a posix name */
+       status = pvfs_resolve_name(pvfs, req, pattern, 0, &name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!name->has_wildcard && !name->exists) {
+               return STATUS_NO_MORE_FILES;
+       }
+
+       /* 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_p(req, struct pvfs_search_state);
+       if (!search) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       dir = talloc_p(search, struct pvfs_dir);
+       if (!dir) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* do the actual directory listing */
+       status = pvfs_list(pvfs, name, dir);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /* we need to give a handle back to the client so it
+          can continue a search */
+       status = pvfs_next_search_handle(pvfs, &search->handle, 0x100);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       
+       search->dir = dir;
+       search->current_index = 0;
+       search->search_attrib = search_attrib;
+
+       status = pvfs_search_fill(pvfs, req, io->search_first.in.max_count, search, io->generic.level,
+                                 &reply_count, search_private, callback);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       io->search_first.out.count = reply_count;
+
+       /* not matching any entries is an error */
+       if (reply_count == 0) {
+               return STATUS_NO_MORE_FILES;
+       }
+
+       pvfs->search.num_active_searches++;
+       talloc_steal(pvfs, search);
+       DLIST_ADD(pvfs->search.open_searches, search);
+
+       return NT_STATUS_OK;
+}
+
+/* continue a old style search */
+static NTSTATUS pvfs_search_next_old(struct smbsrv_request *req, union smb_search_next *io, 
+                                    void *search_private, 
+                                    BOOL (*callback)(void *, union smb_search_data *))
+{
+       struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+       struct pvfs_search_state *search;
+       struct pvfs_dir *dir;
+       uint_t reply_count, max_count;
+       uint16_t handle;
+       NTSTATUS status;
+
+       handle    = io->search_next.in.id.handle;
+       max_count = io->search_next.in.max_count;
+
+       for (search=pvfs->search.open_searches; search; search = search->next) {
+               if (search->handle == handle) break;
+       }
+       
+       if (!search) {
+               /* we didn't find the search handle */
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       search->current_index = io->search_next.in.id.server_cookie;
+
+       dir = search->dir;
+
+       status = pvfs_search_fill(pvfs, req, max_count, search, io->generic.level,
+                                 &reply_count, search_private, callback);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       io->search_next.out.count = reply_count;
+
+       /* not matching any entries means end of search */
+       if (reply_count == 0) {
+               DLIST_REMOVE(pvfs->search.open_searches, search);
+               talloc_free(search);
+       }
+
+       return NT_STATUS_OK;
+}
+
 /* 
    list files in a directory matching a wildcard pattern
 */
@@ -265,7 +382,7 @@ NTSTATUS pvfs_search_first(struct smbsrv_request *req, union smb_search_first *i
        struct pvfs_state *pvfs = req->tcon->ntvfs_private;
        struct pvfs_search_state *search;
        uint_t reply_count;
-       uint16_t search_attrib;
+       uint16_t search_attrib, max_count;
        const char *pattern;
        NTSTATUS status;
        struct pvfs_filename *name;
@@ -276,6 +393,7 @@ NTSTATUS pvfs_search_first(struct smbsrv_request *req, union smb_search_first *i
 
        search_attrib = io->t2ffirst.in.search_attrib;
        pattern       = io->t2ffirst.in.pattern;
+       max_count     = io->t2ffirst.in.max_count;
 
        /* resolve the cifs name to a posix name */
        status = pvfs_resolve_name(pvfs, req, pattern, 0, &name);
@@ -308,7 +426,7 @@ NTSTATUS pvfs_search_first(struct smbsrv_request *req, union smb_search_first *i
 
        /* we need to give a handle back to the client so it
           can continue a search */
-       status = pvfs_next_search_handle(pvfs, &search->handle);
+       status = pvfs_next_search_handle(pvfs, &search->handle, 0x10000);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -317,7 +435,7 @@ NTSTATUS pvfs_search_first(struct smbsrv_request *req, union smb_search_first *i
        search->current_index = 0;
        search->search_attrib = search_attrib;
 
-       status = pvfs_search_fill(pvfs, req, io->t2ffirst.in.max_count, search, io->generic.level,
+       status = pvfs_search_fill(pvfs, req, max_count, search, io->generic.level,
                                  &reply_count, search_private, callback);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -340,7 +458,6 @@ NTSTATUS pvfs_search_first(struct smbsrv_request *req, union smb_search_first *i
                talloc_free(search);
        } else {
                pvfs->search.num_active_searches++;
-               pvfs->search.next_search_handle++;
                talloc_steal(pvfs, search);
                DLIST_ADD(pvfs->search.open_searches, search);
        }
@@ -378,10 +495,8 @@ NTSTATUS pvfs_search_next(struct smbsrv_request *req, union smb_search_next *io,
 
        dir = search->dir;
 
-       /* the client might be asking for something other than just continuing
-          with the search */
-       if (!(io->t2fnext.in.flags & FLAG_TRANS2_FIND_CONTINUE) &&
-           io->t2fnext.in.last_name && *io->t2fnext.in.last_name) {
+       /* work out what type of continuation is being used */
+       if (io->t2fnext.in.last_name && *io->t2fnext.in.last_name) {
                /* look backwards first */
                for (i=search->current_index; i > 0; i--) {
                        if (strcmp(io->t2fnext.in.last_name, dir->names[i-1]) == 0) {
@@ -397,6 +512,10 @@ NTSTATUS pvfs_search_next(struct smbsrv_request *req, union smb_search_next *io,
                                goto found;
                        }
                }
+       } else if (io->t2fnext.in.flags & FLAG_TRANS2_FIND_CONTINUE) {
+               /* plain continue - nothing to do */
+       } else {
+               search->current_index = io->t2fnext.in.resume_key;
        }
 
 found: 
@@ -432,12 +551,12 @@ NTSTATUS pvfs_search_close(struct smbsrv_request *req, union smb_search_close *i
        struct pvfs_search_state *search;
        uint16_t handle;
 
-       if (io->generic.level >= RAW_SEARCH_SEARCH) {
-               return pvfs_search_close_old(req, io);
+       if (io->generic.level == RAW_FINDCLOSE_FCLOSE) {
+               handle = io->fclose.in.id.handle;
+       } else {
+               handle = io->findclose.in.handle;
        }
 
-       handle = io->findclose.in.handle;
-
        for (search=pvfs->search.open_searches; search; search = search->next) {
                if (search->handle == handle) break;
        }
index a99958d6c6c7782f12a6cfd8cb9e86272ac43619..acd1b6d417cd5b304911270d80c397a7244d1eec 100644 (file)
@@ -81,8 +81,9 @@ static void find_fill_info(struct smbsrv_request *req,
        SCVAL(p, 21, file->search.attrib);
        srv_push_dos_date(req->smb_conn, p, 22, file->search.write_time);
        SIVAL(p, 26, file->search.size);
-       memset(p+30, ' ', 13);
-       memcpy(p+30, file->search.name, MIN(strlen(file->search.name)+1, 13));
+       memset(p+30, ' ', 12);
+       memcpy(p+30, file->search.name, MIN(strlen(file->search.name)+1, 12));
+       SCVAL(p,42,0);
 }
 
 /* callback function for search first/next */
index 3a469b3a2d6387e723ca70ce2fa5c19277cc6b49..a767cb2a70b849090f5a1a966c1bcea29652f714 100644 (file)
@@ -444,11 +444,11 @@ static NTSTATUS multiple_search(struct smbcli_state *cli,
        } else {
                io.t2ffirst.in.search_attrib = 0;
                io.t2ffirst.in.max_count = per_search;
-               io.t2ffirst.in.flags = 0;
+               io.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE_IF_END;
                io.t2ffirst.in.storage_type = 0;
                io.t2ffirst.in.pattern = pattern;
                if (cont_type == CONT_RESUME_KEY) {
-                       io.t2ffirst.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME | 
+                       io.t2ffirst.in.flags |= FLAG_TRANS2_FIND_REQUIRE_RESUME | 
                                FLAG_TRANS2_FIND_BACKUP_INTENT;
                }
        }
@@ -467,7 +467,7 @@ static NTSTATUS multiple_search(struct smbcli_state *cli,
                        io2.t2fnext.in.handle = io.t2ffirst.out.handle;
                        io2.t2fnext.in.max_count = per_search;
                        io2.t2fnext.in.resume_key = 0;
-                       io2.t2fnext.in.flags = 0;
+                       io2.t2fnext.in.flags = FLAG_TRANS2_FIND_CLOSE_IF_END;
                        io2.t2fnext.in.last_name = "";
                        switch (cont_type) {
                        case CONT_RESUME_KEY:
@@ -488,7 +488,7 @@ static NTSTATUS multiple_search(struct smbcli_state *cli,
                                        printf("Server does not support resume by key\n");
                                        return NT_STATUS_NOT_SUPPORTED;
                                }
-                               io2.t2fnext.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME |
+                               io2.t2fnext.in.flags |= FLAG_TRANS2_FIND_REQUIRE_RESUME |
                                        FLAG_TRANS2_FIND_BACKUP_INTENT;
                                break;
                        case CONT_NAME:
@@ -507,7 +507,7 @@ static NTSTATUS multiple_search(struct smbcli_state *cli,
                                }
                                break;
                        case CONT_FLAGS:
-                               io2.t2fnext.in.flags = FLAG_TRANS2_FIND_CONTINUE;
+                               io2.t2fnext.in.flags |= FLAG_TRANS2_FIND_CONTINUE;
                                break;
                        }
                }
@@ -589,6 +589,7 @@ static BOOL test_many_files(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                enum smb_search_level level;
                enum continue_type cont_type;
        } search_types[] = {
+               {"SEARCH",              "ID",    RAW_SEARCH_SEARCH,              CONT_RESUME_KEY},
                {"BOTH_DIRECTORY_INFO", "NAME",  RAW_SEARCH_BOTH_DIRECTORY_INFO, CONT_NAME},
                {"BOTH_DIRECTORY_INFO", "FLAGS", RAW_SEARCH_BOTH_DIRECTORY_INFO, CONT_FLAGS},
                {"BOTH_DIRECTORY_INFO", "KEY",   RAW_SEARCH_BOTH_DIRECTORY_INFO, CONT_RESUME_KEY},
@@ -600,8 +601,7 @@ static BOOL test_many_files(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                {"EA_SIZE",             "NAME",  RAW_SEARCH_EA_SIZE,             CONT_NAME},
                {"DIRECTORY_INFO",      "FLAGS", RAW_SEARCH_DIRECTORY_INFO,      CONT_FLAGS},
                {"DIRECTORY_INFO",      "KEY",   RAW_SEARCH_DIRECTORY_INFO,      CONT_RESUME_KEY},
-               {"DIRECTORY_INFO",      "NAME",  RAW_SEARCH_DIRECTORY_INFO,      CONT_NAME},
-               {"SEARCH",              "ID",    RAW_SEARCH_SEARCH,              CONT_RESUME_KEY}
+               {"DIRECTORY_INFO",      "NAME",  RAW_SEARCH_DIRECTORY_INFO,      CONT_NAME}
        };
 
        if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||