[PATCH 6/6] Move wbc global variables into global context instead

Matthew Newton mcn4 at leicester.ac.uk
Sun Feb 22 18:21:05 MST 2015


There are some global variables in use in the libwbclient
library. Now that we have a context, move these into it so that
they are thread-safe when the wbcCtx* functions are used.

Signed-off-by: Matthew Newton <matthew-git at newtoncomputing.co.uk>
---
 nsswitch/libwbclient/wbc_pwd.c           |  127 ++++++++++++++++++------------
 nsswitch/libwbclient/wbclient.c          |    9 +++
 nsswitch/libwbclient/wbclient.h          |    4 +
 nsswitch/libwbclient/wbclient_internal.h |    2 +
 4 files changed, 90 insertions(+), 52 deletions(-)

diff --git a/nsswitch/libwbclient/wbc_pwd.c b/nsswitch/libwbclient/wbc_pwd.c
index 0b05133..3bf437c 100644
--- a/nsswitch/libwbclient/wbc_pwd.c
+++ b/nsswitch/libwbclient/wbc_pwd.c
@@ -4,6 +4,7 @@
    Winbind client API
 
    Copyright (C) Gerald (Jerry) Carter 2007
+   Copyright (C) Matthew Newton 2015
 
 
    This library is free software; you can redistribute it and/or
@@ -359,28 +360,24 @@ wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
 	return wbcCtxGetgrgid(NULL, gid, grp);
 }
 
-/** @brief Number of cached passwd structs
- *
- */
-static uint32_t pw_cache_size;
-
-/** @brief Position of the pwent context
- *
- */
-static uint32_t pw_cache_idx;
-
 /** @brief Winbindd response containing the passwd structs
  *
  */
 static struct winbindd_response pw_response;
 
 /* Reset the passwd iterator */
-wbcErr wbcCtxSetpwent(struct wbcContext *ctx)
+wbcErr wbcCtxSetpwent(struct wbcContext *_ctx)
 {
 	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+	struct wbcContext *ctx;
 
-	if (pw_cache_size > 0) {
-		pw_cache_idx = pw_cache_size = 0;
+	ctx = _ctx;
+	if (!ctx) {
+		ctx = &wbcGlobalCtx;
+	}
+
+	if (ctx->pw_cache_size > 0) {
+		ctx->pw_cache_idx = ctx->pw_cache_size = 0;
 		winbindd_free_response(&pw_response);
 	}
 
@@ -400,12 +397,18 @@ wbcErr wbcSetpwent(void)
 }
 
 /* Close the passwd iterator */
-wbcErr wbcCtxEndpwent(struct wbcContext *ctx)
+wbcErr wbcCtxEndpwent(struct wbcContext *_ctx)
 {
 	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+	struct wbcContext *ctx;
+
+	ctx = _ctx;
+	if (!ctx) {
+		ctx = &wbcGlobalCtx;
+	}
 
-	if (pw_cache_size > 0) {
-		pw_cache_idx = pw_cache_size = 0;
+	if (ctx->pw_cache_size > 0) {
+		ctx->pw_cache_idx = ctx->pw_cache_size = 0;
 		winbindd_free_response(&pw_response);
 	}
 
@@ -423,20 +426,26 @@ wbcErr wbcEndpwent(void)
 }
 
 /* Return the next struct passwd* entry from the pwent iterator */
-wbcErr wbcCtxGetpwent(struct wbcContext *ctx, struct passwd **pwd)
+wbcErr wbcCtxGetpwent(struct wbcContext *_ctx, struct passwd **pwd)
 {
 	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
 	struct winbindd_request request;
 	struct winbindd_pw *wb_pw;
+	struct wbcContext *ctx;
+
+	ctx = _ctx;
+	if (!ctx) {
+		ctx = &wbcGlobalCtx;
+	}
 
 	/* If there's a cached result, return that. */
-	if (pw_cache_idx < pw_cache_size) {
+	if (ctx->pw_cache_idx < ctx->pw_cache_size) {
 		goto return_result;
 	}
 
 	/* Otherwise, query winbindd for some entries. */
 
-	pw_cache_idx = 0;
+	ctx->pw_cache_idx = 0;
 
 	winbindd_free_response(&pw_response);
 
@@ -448,17 +457,17 @@ wbcErr wbcCtxGetpwent(struct wbcContext *ctx, struct passwd **pwd)
 
 	BAIL_ON_WBC_ERROR(wbc_status);
 
-	pw_cache_size = pw_response.data.num_entries;
+	ctx->pw_cache_size = pw_response.data.num_entries;
 
 return_result:
 
 	wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
 
-	*pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
+	*pwd = copy_passwd_entry(&wb_pw[ctx->pw_cache_idx]);
 
 	BAIL_ON_PTR_ERROR(*pwd, wbc_status);
 
-	pw_cache_idx++;
+	ctx->pw_cache_idx++;
 
 done:
 	return wbc_status;
@@ -469,28 +478,24 @@ wbcErr wbcGetpwent(struct passwd **pwd)
 	return wbcCtxGetpwent(NULL, pwd);
 }
 
-/** @brief Number of cached group structs
- *
- */
-static uint32_t gr_cache_size;
-
-/** @brief Position of the grent context
- *
- */
-static uint32_t gr_cache_idx;
-
 /** @brief Winbindd response containing the group structs
  *
  */
 static struct winbindd_response gr_response;
 
 /* Reset the group iterator */
-wbcErr wbcCtxSetgrent(struct wbcContext *ctx)
+wbcErr wbcCtxSetgrent(struct wbcContext *_ctx)
 {
 	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+	struct wbcContext *ctx;
+
+	ctx = _ctx;
+	if (!ctx) {
+		ctx = &wbcGlobalCtx;
+	}
 
-	if (gr_cache_size > 0) {
-		gr_cache_idx = gr_cache_size = 0;
+	if (ctx->gr_cache_size > 0) {
+		ctx->gr_cache_idx = ctx->gr_cache_size = 0;
 		winbindd_free_response(&gr_response);
 	}
 
@@ -510,12 +515,18 @@ wbcErr wbcSetgrent(void)
 }
 
 /* Close the group iterator */
-wbcErr wbcCtxEndgrent(struct wbcContext *ctx)
+wbcErr wbcCtxEndgrent(struct wbcContext *_ctx)
 {
 	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+	struct wbcContext *ctx;
 
-	if (gr_cache_size > 0) {
-		gr_cache_idx = gr_cache_size = 0;
+	ctx = _ctx;
+	if (!ctx) {
+		ctx = &wbcGlobalCtx;
+	}
+
+	if (ctx->gr_cache_size > 0) {
+		ctx->gr_cache_idx = ctx->gr_cache_size = 0;
 		winbindd_free_response(&gr_response);
 	}
 
@@ -533,21 +544,27 @@ wbcErr wbcEndgrent(void)
 }
 
 /* Return the next struct group* entry from the pwent iterator */
-wbcErr wbcCtxGetgrent(struct wbcContext *ctx, struct group **grp)
+wbcErr wbcCtxGetgrent(struct wbcContext *_ctx, struct group **grp)
 {
 	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
 	struct winbindd_request request;
 	struct winbindd_gr *wb_gr;
 	uint32_t mem_ofs;
+	struct wbcContext *ctx;
+
+	ctx = _ctx;
+	if (!ctx) {
+		ctx = &wbcGlobalCtx;
+	}
 
 	/* If there's a cached result, return that. */
-	if (gr_cache_idx < gr_cache_size) {
+	if (ctx->gr_cache_idx < ctx->gr_cache_size) {
 		goto return_result;
 	}
 
 	/* Otherwise, query winbindd for some entries. */
 
-	gr_cache_idx = 0;
+	ctx->gr_cache_idx = 0;
 
 	winbindd_free_response(&gr_response);
 
@@ -559,21 +576,21 @@ wbcErr wbcCtxGetgrent(struct wbcContext *ctx, struct group **grp)
 
 	BAIL_ON_WBC_ERROR(wbc_status);
 
-	gr_cache_size = gr_response.data.num_entries;
+	ctx->gr_cache_size = gr_response.data.num_entries;
 
 return_result:
 
 	wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
 
-	mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
-		  gr_cache_size * sizeof(struct winbindd_gr);
+	mem_ofs = wb_gr[ctx->gr_cache_idx].gr_mem_ofs +
+		  ctx->gr_cache_size * sizeof(struct winbindd_gr);
 
-	*grp = copy_group_entry(&wb_gr[gr_cache_idx],
+	*grp = copy_group_entry(&wb_gr[ctx->gr_cache_idx],
 				((char *)gr_response.extra_data.data)+mem_ofs);
 
 	BAIL_ON_PTR_ERROR(*grp, wbc_status);
 
-	gr_cache_idx++;
+	ctx->gr_cache_idx++;
 
 done:
 	return wbc_status;
@@ -585,20 +602,26 @@ wbcErr wbcGetgrent(struct group **grp)
 }
 
 /* Return the next struct group* entry from the pwent iterator */
-wbcErr wbcCtxGetgrlist(struct wbcContext *ctx, struct group **grp)
+wbcErr wbcCtxGetgrlist(struct wbcContext *_ctx, struct group **grp)
 {
 	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
 	struct winbindd_request request;
 	struct winbindd_gr *wb_gr;
+	struct wbcContext *ctx;
+
+	ctx = _ctx;
+	if (!ctx) {
+		ctx = &wbcGlobalCtx;
+	}
 
 	/* If there's a cached result, return that. */
-	if (gr_cache_idx < gr_cache_size) {
+	if (ctx->gr_cache_idx < ctx->gr_cache_size) {
 		goto return_result;
 	}
 
 	/* Otherwise, query winbindd for some entries. */
 
-	gr_cache_idx = 0;
+	ctx->gr_cache_idx = 0;
 
 	winbindd_free_response(&gr_response);
 	ZERO_STRUCT(gr_response);
@@ -611,17 +634,17 @@ wbcErr wbcCtxGetgrlist(struct wbcContext *ctx, struct group **grp)
 
 	BAIL_ON_WBC_ERROR(wbc_status);
 
-	gr_cache_size = gr_response.data.num_entries;
+	ctx->gr_cache_size = gr_response.data.num_entries;
 
 return_result:
 
 	wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
 
-	*grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
+	*grp = copy_group_entry(&wb_gr[ctx->gr_cache_idx], NULL);
 
 	BAIL_ON_PTR_ERROR(*grp, wbc_status);
 
-	gr_cache_idx++;
+	ctx->gr_cache_idx++;
 
 done:
 	return wbc_status;
diff --git a/nsswitch/libwbclient/wbclient.c b/nsswitch/libwbclient/wbclient.c
index 1d50f88..bdf9854 100644
--- a/nsswitch/libwbclient/wbclient.c
+++ b/nsswitch/libwbclient/wbclient.c
@@ -39,6 +39,15 @@ NSS_STATUS winbindd_priv_request_response(struct winbindd_context *wbctx,
 struct winbindd_context *winbindd_ctx_create(void);
 void winbindd_ctx_free(struct winbindd_context *ctx);
 
+/* Global context used for non-Ctx functions */
+
+static struct wbcContext wbcGlobalCtx = {
+	.winbindd_ctx = NULL,
+	.pw_cache_size = 0,
+	.pw_cache_idx = 0,
+	.gr_cache_size = 0,
+	.gr_cache_idx = 0
+};
 
 /*
  result == NSS_STATUS_UNAVAIL: winbind not around
diff --git a/nsswitch/libwbclient/wbclient.h b/nsswitch/libwbclient/wbclient.h
index 7994621..8e4d0a1 100644
--- a/nsswitch/libwbclient/wbclient.h
+++ b/nsswitch/libwbclient/wbclient.h
@@ -103,6 +103,10 @@ struct wbcInterfaceDetails {
 
 struct wbcContext {
 	void *winbindd_ctx;     /* winbindd context */
+	uint32_t pw_cache_size; /* Number of cached passwd structs */
+	uint32_t pw_cache_idx;  /* Position of the pwent context */
+	uint32_t gr_cache_size; /* Number of cached group structs */
+	uint32_t gr_cache_idx;  /* Position of the grent context */
 };
 
 /*
diff --git a/nsswitch/libwbclient/wbclient_internal.h b/nsswitch/libwbclient/wbclient_internal.h
index c63180a..1424a2c 100644
--- a/nsswitch/libwbclient/wbclient_internal.h
+++ b/nsswitch/libwbclient/wbclient_internal.h
@@ -38,4 +38,6 @@ void *wbcAllocateMemory(size_t nelem, size_t elsize,
 char *wbcStrDup(const char *str);
 const char **wbcAllocateStringArray(int num_strings);
 
+static struct wbcContext wbcGlobalCtx;
+
 #endif      /* _WBCLIENT_INTERNAL_H */
-- 
1.7.10.4


-- 
Matthew Newton, Ph.D. <mcn4 at le.ac.uk>

Systems Specialist, Infrastructure Services,
I.T. Services, University of Leicester, Leicester LE1 7RH, United Kingdom

For IT help contact helpdesk extn. 2253, <ithelp at le.ac.uk>


More information about the samba-technical mailing list