r23792: convert Samba4 to GPLv3
[kai/samba-autobuild/.git] / source4 / ntvfs / posix / pvfs_search.c
index 58cc1e04f3de2e8391a8cb46711b65f78248d258..cefcee6155bb051e9284a0eee9f17aafb83b6590 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "librpc/gen_ndr/security.h"
 #include "smbd/service_stream.h"
 #include "lib/events/events.h"
-#include "dlinklist.h"
+#include "lib/util/dlinklist.h"
 
 /* place a reasonable limit on old-style searches as clients tend to
    not send search close requests */
 #define MAX_OLD_SEARCHES 2000
+#define MAX_SEARCH_HANDLES (UINT16_MAX - 1)
+#define INVALID_SEARCH_HANDLE UINT16_MAX
 
 /*
   destroy an open search
@@ -58,7 +59,7 @@ static void pvfs_search_timer(struct event_context *ev, struct timed_event *te,
 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;
+       if (search->handle == INVALID_SEARCH_HANDLE) return;
        talloc_free(search->te);
        search->te = event_add_timed(ev, search, 
                                     timeval_current_ofs(search->pvfs->search.inactivity_time, 0), 
@@ -73,12 +74,15 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
                                 const char *unix_path,
                                 const char *fname, 
                                 struct pvfs_search_state *search,
-                                uint32_t dir_index,
+                                off_t dir_offset,
                                 union smb_search_data *file)
 {
        struct pvfs_filename *name;
        NTSTATUS status;
        const char *shortname;
+       uint32_t dir_index = (uint32_t)dir_offset; /* truncated - see the code 
+                                                     in pvfs_list_seek_ofs() for 
+                                                     how we cope with this */
 
        status = pvfs_resolve_partial(pvfs, file, unix_path, fname, &name);
        if (!NT_STATUS_IS_OK(status)) {
@@ -233,7 +237,7 @@ static NTSTATUS pvfs_search_fill(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
                                 enum smb_search_data_level level,
                                 uint_t *reply_count,
                                 void *search_private, 
-                                BOOL (*callback)(void *, union smb_search_data *))
+                                BOOL (*callback)(void *, const union smb_search_data *))
 {
        struct pvfs_dir *dir = search->dir;
        NTSTATUS status;
@@ -247,7 +251,7 @@ static NTSTATUS pvfs_search_fill(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
        while ((*reply_count) < max_count) {
                union smb_search_data *file;
                const char *name;
-               uint_t ofs = search->current_index;
+               off_t ofs = search->current_index;
 
                name = pvfs_list_next(dir, &search->current_index);
                if (name == NULL) break;
@@ -309,7 +313,7 @@ static void pvfs_search_cleanup(struct pvfs_state *pvfs)
 static NTSTATUS pvfs_search_first_old(struct ntvfs_module_context *ntvfs,
                                      struct ntvfs_request *req, union smb_search_first *io, 
                                      void *search_private, 
-                                     BOOL (*callback)(void *, union smb_search_data *))
+                                     BOOL (*callback)(void *, const union smb_search_data *))
 {
        struct pvfs_dir *dir;
        struct pvfs_state *pvfs = ntvfs->private_data;
@@ -399,7 +403,7 @@ static NTSTATUS pvfs_search_first_old(struct ntvfs_module_context *ntvfs,
 static NTSTATUS pvfs_search_next_old(struct ntvfs_module_context *ntvfs,
                                     struct ntvfs_request *req, union smb_search_next *io, 
                                     void *search_private, 
-                                    BOOL (*callback)(void *, union smb_search_data *))
+                                    BOOL (*callback)(void *, const union smb_search_data *))
 {
        struct pvfs_state *pvfs = ntvfs->private_data;
        struct pvfs_search_state *search;
@@ -417,10 +421,15 @@ static NTSTATUS pvfs_search_next_old(struct ntvfs_module_context *ntvfs,
                return NT_STATUS_INVALID_HANDLE;
        }
 
-       search->current_index = io->search_next.in.id.server_cookie;
-       search->last_used = time(NULL);
        dir = search->dir;
 
+       status = pvfs_list_seek_ofs(dir, io->search_next.in.id.server_cookie, 
+                                   &search->current_index);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       search->last_used = time(NULL);
+
        status = pvfs_search_fill(pvfs, req, max_count, search, io->generic.data_level,
                                  &reply_count, search_private, callback);
        if (!NT_STATUS_IS_OK(status)) {
@@ -443,7 +452,7 @@ static NTSTATUS pvfs_search_next_old(struct ntvfs_module_context *ntvfs,
 static NTSTATUS pvfs_search_first_trans2(struct ntvfs_module_context *ntvfs,
                                         struct ntvfs_request *req, union smb_search_first *io, 
                                         void *search_private, 
-                                        BOOL (*callback)(void *, union smb_search_data *))
+                                        BOOL (*callback)(void *, const union smb_search_data *))
 {
        struct pvfs_dir *dir;
        struct pvfs_state *pvfs = ntvfs->private_data;
@@ -488,7 +497,7 @@ static NTSTATUS pvfs_search_first_trans2(struct ntvfs_module_context *ntvfs,
                return status;
        }
 
-       id = idr_get_new(pvfs->search.idtree, search, UINT16_MAX);
+       id = idr_get_new(pvfs->search.idtree, search, MAX_SEARCH_HANDLES);
        if (id == -1) {
                return NT_STATUS_INSUFFICIENT_RESOURCES;
        }
@@ -539,7 +548,7 @@ static NTSTATUS pvfs_search_first_trans2(struct ntvfs_module_context *ntvfs,
 static NTSTATUS pvfs_search_next_trans2(struct ntvfs_module_context *ntvfs,
                                        struct ntvfs_request *req, union smb_search_next *io, 
                                        void *search_private, 
-                                       BOOL (*callback)(void *, union smb_search_data *))
+                                       BOOL (*callback)(void *, const union smb_search_data *))
 {
        struct pvfs_state *pvfs = ntvfs->private_data;
        struct pvfs_search_state *search;
@@ -555,23 +564,24 @@ static NTSTATUS pvfs_search_next_trans2(struct ntvfs_module_context *ntvfs,
                /* we didn't find the search handle */
                return NT_STATUS_INVALID_HANDLE;
        }
-
+       
        dir = search->dir;
+       
+       status = NT_STATUS_OK;
 
        /* work out what type of continuation is being used */
        if (io->t2fnext.in.last_name && *io->t2fnext.in.last_name) {
                status = pvfs_list_seek(dir, io->t2fnext.in.last_name, &search->current_index);
-               if (!NT_STATUS_IS_OK(status)) {
-                       if (io->t2fnext.in.resume_key) {
-                               search->current_index = io->t2fnext.in.resume_key;
-                       } else {
-                               return status;
-                       }
+               if (!NT_STATUS_IS_OK(status) && io->t2fnext.in.resume_key) {
+                       status = pvfs_list_seek_ofs(dir, io->t2fnext.in.resume_key, 
+                                                   &search->current_index);
                }
-       } else if (io->t2fnext.in.flags & FLAG_TRANS2_FIND_CONTINUE) {
-               /* plain continue - nothing to do */
-       } else {
-               search->current_index = io->t2fnext.in.resume_key;
+       } else if (!(io->t2fnext.in.flags & FLAG_TRANS2_FIND_CONTINUE)) {
+               status = pvfs_list_seek_ofs(dir, io->t2fnext.in.resume_key, 
+                                           &search->current_index);
+       }
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        search->num_ea_names = io->t2fnext.in.num_names;
@@ -599,7 +609,7 @@ static NTSTATUS pvfs_search_next_trans2(struct ntvfs_module_context *ntvfs,
 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 *))
+                                      BOOL (*callback)(void *, const union smb_search_data *))
 {
        struct pvfs_dir *dir;
        struct pvfs_state *pvfs = ntvfs->private_data;
@@ -669,10 +679,10 @@ static NTSTATUS pvfs_search_first_smb2(struct ntvfs_module_context *ntvfs,
        NT_STATUS_NOT_OK_RETURN(status);
 
        search->pvfs            = pvfs;
-       search->handle          = -1;
+       search->handle          = INVALID_SEARCH_HANDLE;
        search->dir             = dir;
        search->current_index   = 0;
-       search->search_attrib   = 0;
+       search->search_attrib   = 0x0000FFFF;
        search->must_attrib     = 0;
        search->last_used       = 0;
        search->num_ea_names    = 0;
@@ -702,7 +712,7 @@ static NTSTATUS pvfs_search_first_smb2(struct ntvfs_module_context *ntvfs,
 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 *))
+                                     BOOL (*callback)(void *, const union smb_search_data *))
 {
        struct pvfs_state *pvfs = ntvfs->private_data;
        struct pvfs_search_state *search;
@@ -755,7 +765,7 @@ static NTSTATUS pvfs_search_next_smb2(struct ntvfs_module_context *ntvfs,
 NTSTATUS pvfs_search_first(struct ntvfs_module_context *ntvfs,
                           struct ntvfs_request *req, union smb_search_first *io, 
                           void *search_private, 
-                          BOOL (*callback)(void *, union smb_search_data *))
+                          BOOL (*callback)(void *, const union smb_search_data *))
 {
        switch (io->generic.level) {
        case RAW_SEARCH_SEARCH:
@@ -777,7 +787,7 @@ NTSTATUS pvfs_search_first(struct ntvfs_module_context *ntvfs,
 NTSTATUS pvfs_search_next(struct ntvfs_module_context *ntvfs,
                          struct ntvfs_request *req, union smb_search_next *io, 
                          void *search_private, 
-                         BOOL (*callback)(void *, union smb_search_data *))
+                         BOOL (*callback)(void *, const union smb_search_data *))
 {
        switch (io->generic.level) {
        case RAW_SEARCH_SEARCH:
@@ -804,7 +814,7 @@ NTSTATUS pvfs_search_close(struct ntvfs_module_context *ntvfs,
 {
        struct pvfs_state *pvfs = ntvfs->private_data;
        struct pvfs_search_state *search;
-       uint16_t handle = 0;
+       uint16_t handle = INVALID_SEARCH_HANDLE;
 
        switch (io->generic.level) {
        case RAW_FINDCLOSE_GENERIC: