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,
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
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),
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)) {
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;
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;
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;
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;
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)) {
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;
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;
}
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;
/* 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;
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;
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;
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;
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:
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:
{
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: