aboutsummaryrefslogtreecommitdiff
path: root/inet
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-10-07 10:06:31 -0400
committerUlrich Drepper <drepper@gmail.com>2011-10-07 10:06:31 -0400
commit684ae515993269277448150a1ca70db3b94aa5bd (patch)
tree493609057fdfc4aa2dd41f8d6e0c2047616b5d9c /inet
parent21fd49a9ef9c21cd2c87d0facf9f53bedb5cea20 (diff)
downloadglibc-684ae515993269277448150a1ca70db3b94aa5bd.zip
glibc-684ae515993269277448150a1ca70db3b94aa5bd.tar.gz
glibc-684ae515993269277448150a1ca70db3b94aa5bd.tar.bz2
Implement caching of nscd
Diffstat (limited to 'inet')
-rw-r--r--inet/getnetgrent_r.c65
1 files changed, 60 insertions, 5 deletions
diff --git a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c
index 6aaba7b..8790387 100644
--- a/inet/getnetgrent_r.c
+++ b/inet/getnetgrent_r.c
@@ -28,6 +28,7 @@
#include "netgroup.h"
#include "nsswitch.h"
#include <sysdep.h>
+#include <nscd/nscd_proto.h>
/* Protect above variable against multiple uses at the same time. */
@@ -101,7 +102,7 @@ endnetgrent_hook (struct __netgrent *datap)
{
enum nss_status (*endfct) (struct __netgrent *);
- if (datap->nip == NULL)
+ if (datap->nip == NULL || datap->nip == (service_user *) -1l)
return;
endfct = __nss_lookup_function (datap->nip, "endnetgrent");
@@ -189,8 +190,21 @@ setnetgrent (const char *group)
__libc_lock_lock (lock);
+ if (__nss_not_use_nscd_netgroup > 0
+ && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY)
+ __nss_not_use_nscd_netgroup = 0;
+
+ if (!__nss_not_use_nscd_netgroup
+ && !__nss_database_custom[NSS_DBSIDX_netgroup])
+ {
+ result = __nscd_setnetgrent (group, &dataset);
+ if (result >= 0)
+ goto out;
+ }
+
result = internal_setnetgrent (group, &dataset);
+ out:
__libc_lock_unlock (lock);
return result;
@@ -226,6 +240,26 @@ int internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
char *buffer, size_t buflen, int *errnop);
libc_hidden_proto (internal_getnetgrent_r)
+
+static enum nss_status
+nscd_getnetgrent (struct __netgrent *datap, char *buffer, size_t buflen,
+ int *errnop)
+{
+ if (datap->cursor >= datap->data + datap->data_size)
+ return NSS_STATUS_UNAVAIL;
+
+ datap->type = triple_val;
+ datap->val.triple.host = datap->cursor;
+ datap->cursor = (char *) rawmemchr (datap->cursor, '\0') + 1;
+ datap->val.triple.user = datap->cursor;
+ datap->cursor = (char *) rawmemchr (datap->cursor, '\0') + 1;
+ datap->val.triple.domain = datap->cursor;
+ datap->cursor = (char *) rawmemchr (datap->cursor, '\0') + 1;
+
+ return NSS_STATUS_SUCCESS;
+}
+
+
int
internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
struct __netgrent *datap,
@@ -239,9 +273,18 @@ internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
/* Run through available functions, starting with the same function last
run. We will repeat each function as long as it succeeds, and then go
on to the next service action. */
- int no_more = (datap->nip == NULL
- || (fct = __nss_lookup_function (datap->nip, "getnetgrent_r"))
- == NULL);
+ int no_more = datap->nip == NULL;
+ if (! no_more)
+ {
+ if (datap->nip == (service_user *) -1l)
+ fct = nscd_getnetgrent;
+ else
+ {
+ fct = __nss_lookup_function (datap->nip, "getnetgrent_r");
+ no_more = fct == NULL;
+ }
+ }
+
while (! no_more)
{
status = DL_CALL_FCT (*fct, (datap, buffer, buflen, &errno));
@@ -342,6 +385,18 @@ int
innetgr (const char *netgroup, const char *host, const char *user,
const char *domain)
{
+ if (__nss_not_use_nscd_netgroup > 0
+ && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY)
+ __nss_not_use_nscd_netgroup = 0;
+
+ if (!__nss_not_use_nscd_netgroup
+ && !__nss_database_custom[NSS_DBSIDX_netgroup])
+ {
+ int result = __nscd_innetgr (netgroup, host, user, domain);
+ if (result >= 0)
+ return result;
+ }
+
union
{
enum nss_status (*f) (const char *, struct __netgrent *);
@@ -453,7 +508,7 @@ innetgr (const char *netgroup, const char *host, const char *user,
entry.needed_groups = tmp->next;
tmp->next = entry.known_groups;
entry.known_groups = tmp;
- current_group = entry.known_groups->name;
+ current_group = tmp->name;
continue;
}