libwbclient: Implement wbcGetpwent
authorKai Blin <kai@samba.org>
Sun, 23 Nov 2008 15:36:01 +0000 (16:36 +0100)
committerKai Blin <kai@samba.org>
Tue, 25 Nov 2008 08:28:25 +0000 (09:28 +0100)
source3/nsswitch/libwbclient/wbc_pwd.c

index 70d3f3ce9d12db0700eb0190f82d685eceb76935..87908bb5e7f7132c55065594082e07a5c65aa99f 100644 (file)
 
 #include "libwbclient.h"
 
+/** @brief The maximum number of pwent structs to get from winbindd
+ *
+ */
+#define MAX_GETPWENT_USERS 500
+
 /**
  *
  **/
@@ -284,6 +289,21 @@ wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
        return wbc_status;
 }
 
+/** @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;
+
 /** @brief Reset the passwd iterator
  *
  * @return #wbcErr
@@ -293,6 +313,15 @@ wbcErr wbcSetpwent(void)
 {
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
 
+       if (pw_cache_size > 0) {
+               pw_cache_idx = pw_cache_size = 0;
+               if (pw_response.extra_data.data) {
+                       free(pw_response.extra_data.data);
+               }
+       }
+
+       ZERO_STRUCT(pw_response);
+
        wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
                                        NULL, NULL);
        BAIL_ON_WBC_ERROR(wbc_status);
@@ -310,6 +339,13 @@ wbcErr wbcEndpwent(void)
 {
        wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
 
+       if (pw_cache_size > 0) {
+               pw_cache_idx = pw_cache_size = 0;
+               if (pw_response.extra_data.data) {
+                       free(pw_response.extra_data.data);
+               }
+       }
+
        wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
                                        NULL, NULL);
        BAIL_ON_WBC_ERROR(wbc_status);
@@ -320,14 +356,53 @@ wbcErr wbcEndpwent(void)
 
 /** @brief Return the next struct passwd* entry from the pwent iterator
  *
- * @param **pwd       Pointer to resulting struct group* from the query.
+ * @param **pwd       Pointer to resulting struct passwd* from the query.
  *
  * @return #wbcErr
  **/
 
 wbcErr wbcGetpwent(struct passwd **pwd)
 {
-       return WBC_ERR_NOT_IMPLEMENTED;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+       struct winbindd_request request;
+       struct winbindd_pw *wb_pw;
+
+       /* If there's a cached result, return that. */
+       if (pw_cache_idx < pw_cache_size) {
+               goto return_result;
+       }
+
+       /* Otherwise, query winbindd for some entries. */
+
+       pw_cache_idx = 0;
+
+       if (pw_response.extra_data.data) {
+               free(pw_response.extra_data.data);
+               ZERO_STRUCT(pw_response);
+       }
+
+       ZERO_STRUCT(request);
+       request.data.num_entries = MAX_GETPWENT_USERS;
+
+       wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
+                                       &pw_response);
+
+       BAIL_ON_WBC_ERROR(wbc_status);
+
+       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]);
+
+       BAIL_ON_PTR_ERROR(*pwd, wbc_status);
+
+       pw_cache_idx++;
+
+done:
+       return wbc_status;
 }
 
 /** @brief Reset the group iterator