The branch, v3-6-test has been updated via 357377d s3: Properly print binary values "net cache" via 6662a18 s3: Add gencache_iterate_blobs via 576cefd s3: Convert gencache_get_data_blob to gencache_parse via f0e470d s3: Add gencache_parse via 9c66cff s3: Use localtime_r, libreplace defines it via 262dd7d libwbclient: Correctly order the wbcAllocateMemory args via e0a080d libwbclient: Fix a division by zero from 19d20dc s3:winbind correct a copy&paste error
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test - Log ----------------------------------------------------------------- commit 357377d309a05bb8b54d04944a0bd43b8414868d Author: Volker Lendecke <v...@samba.org> Date: Sun Nov 28 13:14:38 2010 +0100 s3: Properly print binary values "net cache" Autobuild-User: Volker Lendecke <vlen...@samba.org> Autobuild-Date: Sun Nov 28 15:03:26 CET 2010 on sn-devel-104 commit 6662a18f8b0fc02c9018983758ee74811a807925 Author: Volker Lendecke <v...@samba.org> Date: Sat Nov 27 15:48:21 2010 +0100 s3: Add gencache_iterate_blobs commit 576cefdd5e5887d08cc9fa380e5de986e1c6c898 Author: Volker Lendecke <v...@samba.org> Date: Sat Nov 27 11:36:52 2010 +0100 s3: Convert gencache_get_data_blob to gencache_parse commit f0e470d82aea84cc4c3e19e7b0bb533bbbfd29bc Author: Volker Lendecke <v...@samba.org> Date: Sat Nov 27 00:40:25 2010 +0100 s3: Add gencache_parse commit 9c66cff6cbd19ffd58983748b32f8d44d20f8ef1 Author: Volker Lendecke <v...@samba.org> Date: Sat Nov 27 19:52:11 2010 +0100 s3: Use localtime_r, libreplace defines it Autobuild-User: Volker Lendecke <vlen...@samba.org> Autobuild-Date: Sat Nov 27 20:50:27 CET 2010 on sn-devel-104 commit 262dd7d6215d1b5d6570bf3e602f343183f0e63d Author: Volker Lendecke <v...@samba.org> Date: Sat Nov 27 19:07:40 2010 +0100 libwbclient: Correctly order the wbcAllocateMemory args In these cases, it does not make a functional difference. Autobuild-User: Volker Lendecke <vlen...@samba.org> Autobuild-Date: Sat Nov 27 19:56:02 CET 2010 on sn-devel-104 commit e0a080dcfaea689272a3dad41e9f9e33bae266bd Author: Volker Lendecke <v...@samba.org> Date: Sat Nov 27 19:02:33 2010 +0100 libwbclient: Fix a division by zero If wbinfo -r returns no groups, wbcAllocateMemory divides by zero ----------------------------------------------------------------------- Summary of changes: nsswitch/libwbclient/wbc_pam.c | 10 +- nsswitch/libwbclient/wbc_pwd.c | 2 +- nsswitch/libwbclient/wbc_util.c | 12 +- source3/include/proto.h | 7 + source3/lib/gencache.c | 298 ++++++++++++++++++++++++--------------- source3/utils/net_cache.c | 48 ++++--- 6 files changed, 232 insertions(+), 145 deletions(-) Changeset truncated at 500 lines: diff --git a/nsswitch/libwbclient/wbc_pam.c b/nsswitch/libwbclient/wbc_pam.c index 50524d2..1c0f792 100644 --- a/nsswitch/libwbclient/wbc_pam.c +++ b/nsswitch/libwbclient/wbc_pam.c @@ -87,7 +87,7 @@ static wbcErr wbc_create_auth_info(const struct winbindd_response *resp, uint32_t j; i = (struct wbcAuthUserInfo *)wbcAllocateMemory( - sizeof(struct wbcAuthUserInfo), 1, + 1, sizeof(struct wbcAuthUserInfo), wbcAuthUserInfoDestructor); BAIL_ON_PTR_ERROR(i, wbc_status); @@ -248,7 +248,7 @@ static wbcErr wbc_create_error_info(const struct winbindd_response *resp, struct wbcAuthErrorInfo *e; e = (struct wbcAuthErrorInfo *)wbcAllocateMemory( - sizeof(struct wbcAuthErrorInfo), 1, + 1, sizeof(struct wbcAuthErrorInfo), wbcAuthErrorInfoDestructor); BAIL_ON_PTR_ERROR(e, wbc_status); @@ -275,7 +275,7 @@ static wbcErr wbc_create_password_policy_info(const struct winbindd_response *re struct wbcUserPasswordPolicyInfo *i; i = (struct wbcUserPasswordPolicyInfo *)wbcAllocateMemory( - sizeof(struct wbcUserPasswordPolicyInfo), 1, NULL); + 1, sizeof(struct wbcUserPasswordPolicyInfo), NULL); BAIL_ON_PTR_ERROR(i, wbc_status); i->min_passwordage = resp->data.auth.policy.min_passwordage; @@ -306,7 +306,7 @@ static wbcErr wbc_create_logon_info(struct winbindd_response *resp, struct wbcLogonUserInfo *i; i = (struct wbcLogonUserInfo *)wbcAllocateMemory( - sizeof(struct wbcLogonUserInfo), 1, + 1, sizeof(struct wbcLogonUserInfo), wbcLogonUserInfoDestructor); BAIL_ON_PTR_ERROR(i, wbc_status); @@ -1243,7 +1243,7 @@ wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params, } result = (struct wbcCredentialCacheInfo *)wbcAllocateMemory( - sizeof(struct wbcCredentialCacheInfo), 1, + 1, sizeof(struct wbcCredentialCacheInfo), wbcCredentialCacheInfoDestructor); if (result == NULL) { status = WBC_ERR_NO_MEMORY; diff --git a/nsswitch/libwbclient/wbc_pwd.c b/nsswitch/libwbclient/wbc_pwd.c index 1527808..abd03d7 100644 --- a/nsswitch/libwbclient/wbc_pwd.c +++ b/nsswitch/libwbclient/wbc_pwd.c @@ -605,7 +605,7 @@ wbcErr wbcGetGroups(const char *account, BAIL_ON_WBC_ERROR(wbc_status); groups = (gid_t *)wbcAllocateMemory( - sizeof(gid_t), response.data.num_entries, NULL); + response.data.num_entries, sizeof(gid_t), NULL); BAIL_ON_PTR_ERROR(groups, wbc_status); for (i = 0; i < response.data.num_entries; i++) { diff --git a/nsswitch/libwbclient/wbc_util.c b/nsswitch/libwbclient/wbc_util.c index 75b0093..e2e657a 100644 --- a/nsswitch/libwbclient/wbc_util.c +++ b/nsswitch/libwbclient/wbc_util.c @@ -74,7 +74,7 @@ wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details) ZERO_STRUCT(response); info = (struct wbcInterfaceDetails *)wbcAllocateMemory( - sizeof(struct wbcInterfaceDetails), 1, + 1, sizeof(struct wbcInterfaceDetails), wbcInterfaceDetailsDestructor); BAIL_ON_PTR_ERROR(info, wbc_status); @@ -173,7 +173,7 @@ wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo) BAIL_ON_WBC_ERROR(wbc_status); info = (struct wbcDomainInfo *)wbcAllocateMemory( - sizeof(struct wbcDomainInfo), 1, wbcDomainInfoDestructor); + 1, sizeof(struct wbcDomainInfo), wbcDomainInfoDestructor); BAIL_ON_PTR_ERROR(info, wbc_status); info->short_name = strdup(response.data.domain_info.name); @@ -442,7 +442,7 @@ wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains) } d_list = (struct wbcDomainInfo *)wbcAllocateMemory( - sizeof(struct wbcDomainInfo), response.data.num_entries + 1, + response.data.num_entries + 1,sizeof(struct wbcDomainInfo), wbcDomainInfoListDestructor); BAIL_ON_PTR_ERROR(d_list, wbc_status); @@ -511,7 +511,7 @@ wbcErr wbcLookupDomainController(const char *domain, request.flags = flags; dc = (struct wbcDomainControllerInfo *)wbcAllocateMemory( - sizeof(struct wbcDomainControllerInfo), 1, + 1, sizeof(struct wbcDomainControllerInfo), wbcDomainControllerInfoDestructor); BAIL_ON_PTR_ERROR(dc, wbc_status); @@ -554,7 +554,7 @@ static wbcErr wbc_create_domain_controller_info_ex(const struct winbindd_respons struct wbcGuid guid; i = (struct wbcDomainControllerInfoEx *)wbcAllocateMemory( - sizeof(struct wbcDomainControllerInfoEx), 1, + 1, sizeof(struct wbcDomainControllerInfoEx), wbcDomainControllerInfoExDestructor); BAIL_ON_PTR_ERROR(i, wbc_status); @@ -698,7 +698,7 @@ wbcErr wbcAddNamedBlob(size_t *num_blobs, * wbcNamedBlobDestructor */ blobs = (struct wbcNamedBlob *)wbcAllocateMemory( - sizeof(struct wbcNamedBlob), *num_blobs + 2, + *num_blobs + 2, sizeof(struct wbcNamedBlob), wbcNamedBlobDestructor); if (*pblobs != NULL) { diff --git a/source3/include/proto.h b/source3/include/proto.h index 33017aa..c1840a4 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -595,10 +595,17 @@ void pull_file_id_24(char *buf, struct file_id *id); bool gencache_set(const char *keystr, const char *value, time_t timeout); bool gencache_del(const char *keystr); bool gencache_get(const char *keystr, char **valstr, time_t *timeout); +bool gencache_parse(const char *keystr, + void (*parser)(time_t timeout, DATA_BLOB blob, + void *private_data), + void *private_data); bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, time_t *timeout, bool *was_expired); bool gencache_stabilize(void); bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob, time_t timeout); +void gencache_iterate_blobs(void (*fn)(const char *key, DATA_BLOB value, + time_t timeout, void *private_data), + void *private_data, const char *pattern); void gencache_iterate(void (*fn)(const char* key, const char *value, time_t timeout, void* dptr), void* data, const char* keystr_pattern); diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index 8d2ddb2..db0b179 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -274,6 +274,10 @@ static bool gencache_pull_timeout(char *val, time_t *pres, char **pendptr) time_t res; char *endptr; + if (val == NULL) { + return false; + } + res = strtol(val, &endptr, 10); if ((endptr == NULL) || (*endptr != '/')) { @@ -289,69 +293,124 @@ static bool gencache_pull_timeout(char *val, time_t *pres, char **pendptr) return true; } -/** - * Get existing entry from the cache file. - * - * @param keystr string that represents a key of this entry - * @param blob DATA_BLOB that is filled with entry's blob - * @param timeout pointer to a time_t that is filled with entry's - * timeout - * - * @retval true when entry is successfuly fetched - * @retval False for failure - **/ +struct gencache_parse_state { + void (*parser)(time_t timeout, DATA_BLOB blob, void *private_data); + void *private_data; +}; -bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, - time_t *timeout, bool *was_expired) +static int gencache_parse_fn(TDB_DATA key, TDB_DATA data, void *private_data) { - TDB_DATA databuf; + struct gencache_parse_state *state; + DATA_BLOB blob; time_t t; char *endptr; - bool expired = false; + bool ret; - if (keystr == NULL) { - goto fail; + if (data.dptr == NULL) { + return -1; + } + ret = gencache_pull_timeout((char *)data.dptr, &t, &endptr); + if (!ret) { + return -1; } + state = (struct gencache_parse_state *)private_data; + blob = data_blob_const( + endptr+1, data.dsize - PTR_DIFF(endptr+1, data.dptr)); + state->parser(t, blob, state->private_data); + return 0; +} + +bool gencache_parse(const char *keystr, + void (*parser)(time_t timeout, DATA_BLOB blob, + void *private_data), + void *private_data) +{ + struct gencache_parse_state state; + TDB_DATA key; + int ret; + if (keystr == NULL) { + return false; + } if (tdb_data_cmp(string_term_tdb_data(keystr), last_stabilize_key()) == 0) { - DEBUG(10, ("Can't get %s as a key\n", keystr)); - goto fail; + return false; } - if (!gencache_init()) { - goto fail; + return false; } - databuf = tdb_fetch_bystring(cache_notrans, keystr); + key = string_term_tdb_data(keystr); + state.parser = parser; + state.private_data = private_data; - if (databuf.dptr == NULL) { - databuf = tdb_fetch_bystring(cache, keystr); + ret = tdb_parse_record(cache_notrans, key, gencache_parse_fn, &state); + if (ret != -1) { + return true; } + ret = tdb_parse_record(cache, key, gencache_parse_fn, &state); + return (ret != -1); +} - if (databuf.dptr == NULL) { - DEBUG(10, ("Cache entry with key = %s couldn't be found \n", - keystr)); - goto fail; - } +struct gencache_get_data_blob_state { + DATA_BLOB *blob; + time_t timeout; + bool result; +}; - if (!gencache_pull_timeout((char *)databuf.dptr, &t, &endptr)) { - SAFE_FREE(databuf.dptr); - goto fail; +static void gencache_get_data_blob_parser(time_t timeout, DATA_BLOB blob, + void *private_data) +{ + struct gencache_get_data_blob_state *state = + (struct gencache_get_data_blob_state *)private_data; + + if (timeout == 0) { + state->result = false; + return; } + state->timeout = timeout; - DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " - "timeout = %s", t > time(NULL) ? "valid" : - "expired", keystr, endptr+1, ctime(&t))); + if (state->blob == NULL) { + state->result = true; + return; + } - if (t == 0) { - /* Deleted */ - SAFE_FREE(databuf.dptr); - goto fail; + *state->blob = data_blob(blob.data, blob.length); + if (state->blob->data == NULL) { + state->result = false; + return; } + state->result = true; +} + +/** + * Get existing entry from the cache file. + * + * @param keystr string that represents a key of this entry + * @param blob DATA_BLOB that is filled with entry's blob + * @param timeout pointer to a time_t that is filled with entry's + * timeout + * + * @retval true when entry is successfuly fetched + * @retval False for failure + **/ + +bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, + time_t *timeout, bool *was_expired) +{ + struct gencache_get_data_blob_state state; + bool expired = false; - if (t <= time(NULL)) { + state.result = false; + state.blob = blob; + if (!gencache_parse(keystr, gencache_get_data_blob_parser, &state)) { + goto fail; + } + if (!state.result) { + goto fail; + } + if (state.timeout <= time(NULL)) { /* * We're expired, delete the entry. We can't use gencache_del * here, because that uses gencache_get_data_blob for checking @@ -359,28 +418,11 @@ bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, * directly store an empty value with 0 timeout. */ gencache_set(keystr, "", 0); - - SAFE_FREE(databuf.dptr); - expired = true; goto fail; } - - if (blob != NULL) { - *blob = data_blob( - endptr+1, - databuf.dsize - PTR_DIFF(endptr+1, databuf.dptr)); - if (blob->data == NULL) { - SAFE_FREE(databuf.dptr); - DEBUG(0, ("memdup failed\n")); - goto fail; - } - } - - SAFE_FREE(databuf.dptr); - if (timeout) { - *timeout = t; + *timeout = state.timeout; } return True; @@ -593,42 +635,27 @@ bool gencache_set(const char *keystr, const char *value, time_t timeout) return gencache_set_data_blob(keystr, &blob, timeout); } -/** - * Iterate through all entries which key matches to specified pattern - * - * @param fn pointer to the function that will be supplied with each single - * matching cache entry (key, value and timeout) as an arguments - * @param data void pointer to an arbitrary data that is passed directly to the fn - * function on each call - * @param keystr_pattern pattern the existing entries' keys are matched to - * - **/ - -struct gencache_iterate_state { - void (*fn)(const char *key, const char *value, time_t timeout, - void *priv); +struct gencache_iterate_blobs_state { + void (*fn)(const char *key, DATA_BLOB value, + time_t timeout, void *private_data); const char *pattern; - void *priv; + void *private_data; bool in_persistent; }; -static int gencache_iterate_fn(struct tdb_context *tdb, TDB_DATA key, - TDB_DATA value, void *priv) +static int gencache_iterate_blobs_fn(struct tdb_context *tdb, TDB_DATA key, + TDB_DATA data, void *priv) { - struct gencache_iterate_state *state = - (struct gencache_iterate_state *)priv; + struct gencache_iterate_blobs_state *state = + (struct gencache_iterate_blobs_state *)priv; char *keystr; char *free_key = NULL; - char *valstr; - char *free_val = NULL; - unsigned long u; time_t timeout; - char *timeout_endp; + char *endptr; if (tdb_data_cmp(key, last_stabilize_key()) == 0) { return 0; } - if (state->in_persistent && tdb_exists(cache_notrans, key)) { return 0; } @@ -641,62 +668,103 @@ static int gencache_iterate_fn(struct tdb_context *tdb, TDB_DATA key, free_key = keystr; } - if ((value.dptr == NULL) || (value.dsize <= TIMEOUT_LEN)) { + if (!gencache_pull_timeout((char *)data.dptr, &timeout, &endptr)) { goto done; } + endptr += 1; if (fnmatch(state->pattern, keystr, 0) != 0) { goto done; } - if (value.dptr[value.dsize-1] == '\0') { - valstr = (char *)value.dptr; - } else { - /* ensure 0-termination */ - valstr = SMB_STRNDUP((char *)value.dptr, value.dsize); - free_val = valstr; - } - - u = strtoul(valstr, &timeout_endp, 10); - - if ((*timeout_endp != '/') || ((timeout_endp-valstr) != TIMEOUT_LEN)) { - goto done; - } - - timeout = u; - timeout_endp += 1; + DEBUG(10, ("Calling function with arguments (key=%s, timeout=%s)\n", + keystr, ctime(&timeout))); - DEBUG(10, ("Calling function with arguments " - "(key = %s, value = %s, timeout = %s)\n", - keystr, timeout_endp, ctime(&timeout))); - state->fn(keystr, timeout_endp, timeout, state->priv); + state->fn(keystr, + data_blob_const(endptr, + data.dsize - PTR_DIFF(endptr, data.dptr)), + timeout, state->private_data); done: SAFE_FREE(free_key); - SAFE_FREE(free_val); return 0; } -void gencache_iterate(void (*fn)(const char* key, const char *value, time_t timeout, void* dptr), - void* data, const char* keystr_pattern) +void gencache_iterate_blobs(void (*fn)(const char *key, DATA_BLOB value, + time_t timeout, void *private_data), + void *private_data, const char *pattern) { - struct gencache_iterate_state state; + struct gencache_iterate_blobs_state state; - if ((fn == NULL) || (keystr_pattern == NULL)) { + if ((fn == NULL) || (pattern == NULL) || !gencache_init()) { return; } - if (!gencache_init()) return; - - DEBUG(5, ("Searching cache keys with pattern %s\n", keystr_pattern)); + DEBUG(5, ("Searching cache keys with pattern %s\n", pattern)); state.fn = fn; - state.pattern = keystr_pattern; - state.priv = data; + state.pattern = pattern; + state.private_data = private_data; state.in_persistent = false; - tdb_traverse(cache_notrans, gencache_iterate_fn, &state); + tdb_traverse(cache_notrans, gencache_iterate_blobs_fn, &state); state.in_persistent = true; - tdb_traverse(cache, gencache_iterate_fn, &state); + tdb_traverse(cache, gencache_iterate_blobs_fn, &state); +} + +/** + * Iterate through all entries which key matches to specified pattern + * + * @param fn pointer to the function that will be supplied with each single + * matching cache entry (key, value and timeout) as an arguments + * @param data void pointer to an arbitrary data that is passed directly to the fn + * function on each call + * @param keystr_pattern pattern the existing entries' keys are matched to + * + **/ + +struct gencache_iterate_state { + void (*fn)(const char *key, const char *value, time_t timeout, + void *priv); -- Samba Shared Repository