diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/smb_server/smb/search.c | 86 |
1 files changed, 60 insertions, 26 deletions
diff --git a/source4/smb_server/smb/search.c b/source4/smb_server/smb/search.c index 297ea40063..71d5ce6cfc 100644 --- a/source4/smb_server/smb/search.c +++ b/source4/smb_server/smb/search.c @@ -45,13 +45,13 @@ }} while (0) /* useful wrapper for talloc with NO_MEMORY reply */ -#define REQ_TALLOC(ptr) do { \ - ptr = talloc_size(req, sizeof(*(ptr))); \ +#define REQ_TALLOC(ptr, type) do { \ + ptr = talloc(req, type); \ if (!ptr) { \ smbsrv_send_error(req, NT_STATUS_NO_MEMORY); \ return; \ }} while (0) - + #define CHECK_MIN_BLOB_SIZE(blob, size) do { \ if ((blob)->length < (size)) { \ return NT_STATUS_INFO_LENGTH_MISMATCH; \ @@ -104,16 +104,46 @@ static BOOL find_callback(void *private, union smb_search_data *file) } /**************************************************************************** + Reply to a search first (async reply) +****************************************************************************/ +static void reply_search_first_send(struct smbsrv_request *req) +{ + union smb_search_first *sf; + + CHECK_ASYNC_STATUS; + + sf = talloc_get_type(req->async_states->private_data, union smb_search_first); + + SSVAL(req->out.vwv, VWV(0), sf->search_first.out.count); + + smbsrv_send_reply(req); +} + +/**************************************************************************** + Reply to a search next (async reply) +****************************************************************************/ +static void reply_search_next_send(struct smbsrv_request *req) +{ + union smb_search_next *sn; + + CHECK_ASYNC_STATUS; + + sn = talloc_get_type(req->async_states->private_data, union smb_search_next); + + SSVAL(req->out.vwv, VWV(0), sn->search_next.out.count); + + smbsrv_send_reply(req); +} + +/**************************************************************************** Reply to a search. ****************************************************************************/ void smbsrv_reply_search(struct smbsrv_request *req) { union smb_search_first *sf; - union smb_search_next *sn; uint16_t resume_key_length; - struct search_state state; + struct search_state *state; uint8_t *p; - NTSTATUS status; enum smb_search_level level = RAW_SEARCH_SEARCH; uint8_t op = CVAL(req->in.hdr,HDR_COM); @@ -123,13 +153,13 @@ void smbsrv_reply_search(struct smbsrv_request *req) level = RAW_SEARCH_FUNIQUE; } - REQ_TALLOC(sf); - /* parse request */ if (req->in.wct != 2) { smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER); return; } + + REQ_TALLOC(sf, union smb_search_first); p = req->in.data; p += req_pull_ascii4(req, &sf->search_first.in.pattern, @@ -151,15 +181,19 @@ void smbsrv_reply_search(struct smbsrv_request *req) p += 3; /* setup state for callback */ - state.req = req; - state.file = NULL; - state.last_entry_offset = 0; - + REQ_TALLOC(state, struct search_state); + state->req = req; + state->file = NULL; + state->last_entry_offset = 0; + /* construct reply */ smbsrv_setup_reply(req, 1, 0); + SSVAL(req->out.vwv, VWV(0), 0); req_append_var_block(req, NULL, 0); if (resume_key_length != 0) { + union smb_search_next *sn; + if (resume_key_length != 21 || req_data_oob(req, p, 21) || level == RAW_SEARCH_FUNIQUE) { @@ -168,7 +202,7 @@ void smbsrv_reply_search(struct smbsrv_request *req) } /* do a search next operation */ - REQ_TALLOC(sn); + REQ_TALLOC(sn, union smb_search_next); sn->search_next.in.id.reserved = CVAL(p, 0); memcpy(sn->search_next.in.id.name, p+1, 11); @@ -179,27 +213,27 @@ void smbsrv_reply_search(struct smbsrv_request *req) sn->search_next.level = level; sn->search_next.in.max_count = SVAL(req->in.vwv, VWV(0)); sn->search_next.in.search_attrib = SVAL(req->in.vwv, VWV(1)); - + + req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC; + req->async_states->send_fn = reply_search_next_send; + req->async_states->private_data = sn; + /* call backend */ - status = ntvfs_search_next(req, sn, &state, find_callback); - SSVAL(req->out.vwv, VWV(0), sn->search_next.out.count); + req->async_states->status = ntvfs_search_next(req, sn, state, find_callback); } else { /* do a search first operation */ sf->search_first.level = level; sf->search_first.in.search_attrib = SVAL(req->in.vwv, VWV(1)); sf->search_first.in.max_count = SVAL(req->in.vwv, VWV(0)); - - /* call backend */ - status = ntvfs_search_first(req, sf, &state, find_callback); - SSVAL(req->out.vwv, VWV(0), sf->search_first.out.count); - } - if (!NT_STATUS_IS_OK(status)) { - smbsrv_send_error(req, status); - return; + req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC; + req->async_states->send_fn = reply_search_first_send; + req->async_states->private_data = sf; + + req->async_states->status = ntvfs_search_first(req, sf, state, find_callback); } - smbsrv_send_reply(req); + REQ_ASYNC_TAIL; } @@ -229,7 +263,7 @@ void smbsrv_reply_fclose(struct smbsrv_request *req) uint8_t *p; const char *pattern; - REQ_TALLOC(sc); + REQ_TALLOC(sc, union smb_search_close); /* parse request */ if (req->in.wct != 2) { |