From 6e2bf7e23480cb467288adac145ec2853aeaa11d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Aug 2009 22:50:39 +0200 Subject: s3:winbind: Add async next_pwent --- source3/Makefile.in | 1 + source3/winbindd/wb_next_pwent.c | 150 ++++++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd.h | 7 ++ source3/winbindd/winbindd_proto.h | 6 ++ 4 files changed, 164 insertions(+) create mode 100644 source3/winbindd/wb_next_pwent.c diff --git a/source3/Makefile.in b/source3/Makefile.in index 4304df6e37..c930f2af3c 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1181,6 +1181,7 @@ WINBINDD_OBJ1 = \ winbindd/wb_getgrsid.o \ winbindd/wb_query_user_list.o \ winbindd/wb_fill_pwent.o \ + winbindd/wb_next_pwent.o \ winbindd/winbindd_lookupsid.o \ winbindd/winbindd_lookupname.o \ winbindd/winbindd_sid_to_uid.o \ diff --git a/source3/winbindd/wb_next_pwent.c b/source3/winbindd/wb_next_pwent.c new file mode 100644 index 0000000000..25ab7b38d3 --- /dev/null +++ b/source3/winbindd/wb_next_pwent.c @@ -0,0 +1,150 @@ +/* + Unix SMB/CIFS implementation. + async next_pwent + Copyright (C) Volker Lendecke 2009 + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . +*/ + +#include "includes.h" +#include "winbindd.h" +#include "librpc/gen_ndr/cli_wbint.h" + +struct wb_next_pwent_state { + struct tevent_context *ev; + struct getpwent_state *gstate; + struct winbindd_pw *pw; +}; + +static void wb_next_pwent_fetch_done(struct tevent_req *subreq); +static void wb_next_pwent_fill_done(struct tevent_req *subreq); + +struct tevent_req *wb_next_pwent_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct getpwent_state *gstate, + struct winbindd_pw *pw) +{ + struct tevent_req *req, *subreq; + struct wb_next_pwent_state *state; + + req = tevent_req_create(mem_ctx, &state, struct wb_next_pwent_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->gstate = gstate; + state->pw = pw; + + if (state->gstate->next_user >= state->gstate->num_users) { + TALLOC_FREE(state->gstate->users); + + if (state->gstate->domain == NULL) { + state->gstate->domain = domain_list(); + } else { + state->gstate->domain = state->gstate->domain->next; + } + + if (state->gstate->domain == NULL) { + tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES); + return tevent_req_post(req, ev); + } + subreq = wb_query_user_list_send(state, state->ev, + state->gstate->domain); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, wb_next_pwent_fetch_done, req); + return req; + } + + subreq = wb_fill_pwent_send( + state, state->ev, + &state->gstate->users[state->gstate->next_user], + state->pw); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, wb_next_pwent_fill_done, req); + return req; +} + +static void wb_next_pwent_fetch_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_next_pwent_state *state = tevent_req_data( + req, struct wb_next_pwent_state); + NTSTATUS status; + + status = wb_query_user_list_recv(subreq, state->gstate, + &state->gstate->num_users, + &state->gstate->users); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + /* Ignore errors here, just log it */ + DEBUG(10, ("query_user_list for domain %s returned %s\n", + state->gstate->domain->name, + nt_errstr(status))); + state->gstate->num_users = 0; + } + + if (state->gstate->num_users == 0) { + state->gstate->domain = state->gstate->domain->next; + if (state->gstate->domain == NULL) { + tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES); + return; + } + subreq = wb_query_user_list_send(state, state->ev, + state->gstate->domain); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_next_pwent_fetch_done, req); + return; + } + + state->gstate->next_user = 0; + + subreq = wb_fill_pwent_send( + state, state->ev, + &state->gstate->users[state->gstate->next_user], + state->pw); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_next_pwent_fill_done, req); +} + +static void wb_next_pwent_fill_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_next_pwent_state *state = tevent_req_data( + req, struct wb_next_pwent_state); + NTSTATUS status; + + status = wb_fill_pwent_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + state->gstate->next_user += 1; + tevent_req_done(req); +} + +NTSTATUS wb_next_pwent_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 773496e8ad..454fea70e6 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -79,6 +79,13 @@ struct getent_state { fstring domain_name; }; +struct getpwent_state { + struct winbindd_domain *domain; + int next_user; + int num_users; + struct wbint_userinfo *users; +}; + /* Storage for cached getpwent() user entries */ struct getpwent_user { diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 58a46b5215..f66becae33 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -862,5 +862,11 @@ struct tevent_req *wb_fill_pwent_send(TALLOC_CTX *mem_ctx, struct winbindd_pw *pw); NTSTATUS wb_fill_pwent_recv(struct tevent_req *req); +struct tevent_req *wb_next_pwent_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct getpwent_state *gstate, + struct winbindd_pw *pw); +NTSTATUS wb_next_pwent_recv(struct tevent_req *req); + #endif /* _WINBINDD_PROTO_H_ */ -- cgit