* nis/nss_nis/nis-spwd.c (internal_nis_getspent_r): Remove data

variable.

	* nis/nss-nis.h: Define response_t and intern_t.  Declare _nis_saveit.
	* nis/nss_nis/nis-pwd.c: Remove response_t and intern_t definition.
	(saveit): Renamed to _nis_saveit.  Take parameter which is pointer
	to the intern_t object.  Change all users.
	* nis/nss_nis/nis-grp.c: Remove response_t, intern_t, and saveit
	definition.  Use _nis_saveit instead of saveit.
	* nis/nss_nis/nis-service.c: Likewise.
	* nis/nss_nis/nis-initgroups.c: Likewise.
	(internal_setgrent): Adjust for buffer handling.
	(internal_getgrent_r): Likewise.
	* nis/nss_nis/nis-rpc.c: Likewise.
This commit is contained in:
Ulrich Drepper 2006-04-29 01:14:07 +00:00
parent 4eaa9bb48b
commit e0d4e91d2b
8 changed files with 153 additions and 289 deletions

View File

@ -1,5 +1,20 @@
2006-04-28 Ulrich Drepper <drepper@redhat.com>
* nis/nss_nis/nis-spwd.c (internal_nis_getspent_r): Remove data
variable.
* nis/nss-nis.h: Define response_t and intern_t. Declare _nis_saveit.
* nis/nss_nis/nis-pwd.c: Remove response_t and intern_t definition.
(saveit): Renamed to _nis_saveit. Take parameter which is pointer
to the intern_t object. Change all users.
* nis/nss_nis/nis-grp.c: Remove response_t, intern_t, and saveit
definition. Use _nis_saveit instead of saveit.
* nis/nss_nis/nis-service.c: Likewise.
* nis/nss_nis/nis-initgroups.c: Likewise.
(internal_setgrent): Adjust for buffer handling.
(internal_getgrent_r): Likewise.
* nis/nss_nis/nis-rpc.c: Likewise.
* nis/nss-default.c (vars): Add SETENT_BATCH_READ.
* nis/nss: Document SETENT_BATCH_READ.
* nis/libnsl.h: Define NSS_FLAG_SETENT_BATCH_READ.

View File

@ -36,4 +36,24 @@ yperr2nss (int errval)
return __yperr2nss_tab[(unsigned int) errval];
}
struct response_t
{
struct response_t *next;
size_t size;
char mem[0];
};
typedef struct intern_t
{
struct response_t *start;
struct response_t *next;
size_t offset;
} intern_t;
extern int _nis_saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata) attribute_hidden;
#endif /* nis/nss-nis.h */

View File

@ -41,82 +41,9 @@ __libc_lock_define_initialized (static, lock)
static bool_t new_start = 1;
static char *oldkey;
static int oldkeylen;
struct response_t
{
struct response_t *next;
size_t size;
char mem[0];
};
typedef struct intern_t
{
struct response_t *start;
struct response_t *next;
size_t offset;
} intern_t;
static intern_t intern;
static int
saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
{
if (instatus != YP_TRUE)
return 1;
if (inkey && inkeylen > 0 && inval && invallen > 0)
{
struct response_t *bucket = intern.next;
if (__builtin_expect (bucket == NULL, 0))
{
#define MINSIZE 4096 - 4 * sizeof (void *)
const size_t minsize = MAX (MINSIZE, 2 * (invallen + 1));
bucket = malloc (sizeof (struct response_t) + minsize);
if (bucket == NULL)
/* We have no error code for out of memory. */
return 1;
bucket->next = NULL;
bucket->size = minsize;
intern.start = intern.next = bucket;
intern.offset = 0;
}
else if (__builtin_expect (invallen + 1 > bucket->size - intern.offset,
0))
{
/* We need a new (larger) buffer. */
const size_t newsize = 2 * MAX (bucket->size, invallen + 1);
struct response_t *newp = malloc (sizeof (struct response_t)
+ newsize);
if (newp == NULL)
/* We have no error code for out of memory. */
return 1;
/* Mark the old bucket as full. */
bucket->size = intern.offset;
newp->next = NULL;
newp->size = newsize;
bucket = intern.next = bucket->next = newp;
intern.offset = 0;
}
char *p = mempcpy (&bucket->mem[intern.offset], inval, invallen);
if (__builtin_expect (p[-1] != '\0', 0))
{
*p = '\0';
++invallen;
}
intern.offset += invallen;
}
return 0;
}
static void
internal_nis_endgrent (void)
{
@ -164,8 +91,8 @@ internal_nis_setgrent (void)
struct ypall_callback ypcb;
ypcb.foreach = saveit;
ypcb.data = NULL;
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) &intern;
enum nss_status status = yperr2nss (yp_all (domain, "group.byname", &ypcb));

View File

@ -38,47 +38,6 @@
#define EXTERN_PARSER
#include <nss/nss_files/files-parse.c>
struct response_t
{
struct response_t *next;
char val[0];
};
struct intern_t
{
struct response_t *start;
struct response_t *next;
};
typedef struct intern_t intern_t;
static int
saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
{
intern_t *intern = (intern_t *) indata;
if (instatus != YP_TRUE)
return 1;
if (inkey && inkeylen > 0 && inval && invallen > 0)
{
struct response_t *newp = malloc (sizeof (struct response_t)
+ invallen + 1);
if (newp == NULL)
return 1; /* We have no error code for out of memory */
if (intern->start == NULL)
intern->start = newp;
else
intern->next->next = newp;
intern->next = newp;
newp->next = NULL;
*((char *) mempcpy (newp->val, inval, invallen)) = '\0';
}
return 0;
}
static enum nss_status
internal_setgrent (char *domainname, intern_t *intern)
@ -86,16 +45,21 @@ internal_setgrent (char *domainname, intern_t *intern)
struct ypall_callback ypcb;
enum nss_status status;
intern->start = NULL;
ypcb.foreach = saveit;
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) intern;
status = yperr2nss (yp_all (domainname, "group.byname", &ypcb));
/* Mark the last buffer as full. */
if (intern->next != NULL)
intern->next->size = intern->offset;
intern->next = intern->start;
intern->offset = 0;
return status;
}
static enum nss_status
internal_getgrent_r (struct group *grp, char *buffer, size_t buflen,
int *errnop, intern_t *intern)
@ -107,18 +71,46 @@ internal_getgrent_r (struct group *grp, char *buffer, size_t buflen,
int parse_res;
do
{
if (intern->next == NULL)
return NSS_STATUS_NOTFOUND;
struct response_t *bucket = intern->next;
char *p = strncpy (buffer, intern->next->val, buflen);
while (isspace (*p))
++p;
if (__builtin_expect (intern->offset >= bucket->size, 0))
{
if (bucket->next == NULL)
return NSS_STATUS_NOTFOUND;
/* We look at all the content in the current bucket. Go on
to the next. */
bucket = intern->next = bucket->next;
intern->offset = 0;
}
char *p;
for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
++intern->offset;
size_t len = strlen (p) + 1;
if (__builtin_expect (len > buflen, 0))
{
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
/* We unfortunately have to copy the data in the user-provided
buffer because that buffer might be around for a very long
time and the servent structure must remain valid. If we would
rely on the BUCKET memory the next 'setservent' or 'endservent'
call would destroy it.
The important thing is that it is a single NUL-terminated
string. This is what the parsing routine expects. */
p = memcpy (buffer, &bucket->mem[intern->offset], len);
parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
errnop);
if (__builtin_expect (parse_res == -1, 0))
return NSS_STATUS_TRYAGAIN;
intern->next = intern->next->next;
intern->offset += len;
}
while (!parse_res);
@ -259,7 +251,7 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
char *tmpbuf;
enum nss_status status;
intern_t intern = { NULL, NULL };
intern_t intern = { NULL, NULL, 0 };
gid_t *groups = *groupsp;
status = internal_setgrent (domainname, &intern);

View File

@ -42,34 +42,21 @@ __libc_lock_define_initialized (static, lock)
static bool_t new_start = 1;
static char *oldkey;
static int oldkeylen;
struct response_t
{
struct response_t *next;
size_t size;
char mem[0];
};
typedef struct intern_t
{
struct response_t *start;
struct response_t *next;
size_t offset;
} intern_t;
static intern_t intern;
static int
saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
int
_nis_saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
{
intern_t *intern = (intern_t *) indata;
if (instatus != YP_TRUE)
return 1;
if (inkey && inkeylen > 0 && inval && invallen > 0)
{
struct response_t *bucket = intern.next;
struct response_t *bucket = intern->next;
if (__builtin_expect (bucket == NULL, 0))
{
@ -82,10 +69,10 @@ saveit (int instatus, char *inkey, int inkeylen, char *inval,
bucket->next = NULL;
bucket->size = minsize;
intern.start = intern.next = bucket;
intern.offset = 0;
intern->start = intern->next = bucket;
intern->offset = 0;
}
else if (__builtin_expect (invallen + 1 > bucket->size - intern.offset,
else if (__builtin_expect (invallen + 1 > bucket->size - intern->offset,
0))
{
/* We need a new (larger) buffer. */
@ -97,21 +84,21 @@ saveit (int instatus, char *inkey, int inkeylen, char *inval,
return 1;
/* Mark the old bucket as full. */
bucket->size = intern.offset;
bucket->size = intern->offset;
newp->next = NULL;
newp->size = newsize;
bucket = intern.next = bucket->next = newp;
intern.offset = 0;
bucket = intern->next = bucket->next = newp;
intern->offset = 0;
}
char *p = mempcpy (&bucket->mem[intern.offset], inval, invallen);
char *p = mempcpy (&bucket->mem[intern->offset], inval, invallen);
if (__builtin_expect (p[-1] != '\0', 0))
{
*p = '\0';
++invallen;
}
intern.offset += invallen;
intern->offset += invallen;
}
return 0;
@ -165,8 +152,8 @@ internal_nis_setpwent (void)
struct ypall_callback ypcb;
ypcb.foreach = saveit;
ypcb.data = NULL;
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) &intern;
enum nss_status status = yperr2nss (yp_all (domain, "passwd.byname", &ypcb));

View File

@ -36,59 +36,22 @@
__libc_lock_define_initialized (static, lock)
struct response_t
{
struct response_t *next;
char val[0];
};
static intern_t intern;
struct intern_t
{
struct response_t *start;
struct response_t *next;
};
typedef struct intern_t intern_t;
static intern_t intern = {NULL, NULL};
static int
saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
{
intern_t *intern = (intern_t *) indata;
if (instatus != YP_TRUE)
return 1;
if (inkey && inkeylen > 0 && inval && invallen > 0)
{
struct response_t *newp = malloc (sizeof (struct response_t)
+ invallen + 1);
if (newp == NULL)
return 1; /* We have no error code for out of memory */
if (intern->start == NULL)
intern->start = newp;
else
intern->next->next = newp;
intern->next = newp;
newp->next = NULL;
*((char *) mempcpy (newp->val, inval, invallen)) = '\0';
}
return 0;
}
static void
internal_nis_endrpcent (intern_t *intern)
{
while (intern->start != NULL)
struct response_t *curr = intern->next;
while (curr != NULL)
{
intern->next = intern->start;
intern->start = intern->start->next;
free (intern->next);
struct response_t *last = curr;
curr = curr->next;
free (last);
}
intern->next = intern->start = NULL;
}
static enum nss_status
@ -103,10 +66,16 @@ internal_nis_setrpcent (intern_t *intern)
internal_nis_endrpcent (intern);
ypcb.foreach = saveit;
ypcb.data = (char *)intern;
status = yperr2nss (yp_all(domainname, "rpc.bynumber", &ypcb));
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) intern;
status = yperr2nss (yp_all (domainname, "rpc.bynumber", &ypcb));
/* Mark the last buffer as full. */
if (intern->next != NULL)
intern->next->size = intern->offset;
intern->next = intern->start;
intern->offset = 0;
return status;
}
@ -139,29 +108,56 @@ _nss_nis_endrpcent (void)
static enum nss_status
internal_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen,
int *errnop, intern_t *data)
int *errnop, intern_t *intern)
{
struct parser_data *pdata = (void *) buffer;
int parse_res;
char *p;
if (data->start == NULL)
internal_nis_setrpcent (data);
if (intern->start == NULL)
internal_nis_setrpcent (intern);
/* Get the next entry until we found a correct one. */
do
{
if (data->next == NULL)
return NSS_STATUS_NOTFOUND;
struct response_t *bucket = intern->next;
p = strncpy (buffer, data->next->val, buflen);
while (isspace (*p))
++p;
if (__builtin_expect (intern->offset >= bucket->size, 0))
{
if (bucket->next == NULL)
return NSS_STATUS_NOTFOUND;
/* We look at all the content in the current bucket. Go on
to the next. */
bucket = intern->next = bucket->next;
intern->offset = 0;
}
for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
++intern->offset;
size_t len = strlen (p) + 1;
if (__builtin_expect (len > buflen, 0))
{
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
/* We unfortunately have to copy the data in the user-provided
buffer because that buffer might be around for a very long
time and the servent structure must remain valid. If we would
rely on the BUCKET memory the next 'setservent' or 'endservent'
call would destroy it.
The important thing is that it is a single NUL-terminated
string. This is what the parsing routine expects. */
p = memcpy (buffer, &bucket->mem[intern->offset], len);
parse_res = _nss_files_parse_rpcent (p, rpc, pdata, buflen, errnop);
if (__builtin_expect (parse_res == -1, 0))
return NSS_STATUS_TRYAGAIN;
data->next = data->next->next;
intern->offset += len;
}
while (!parse_res);
@ -193,7 +189,7 @@ _nss_nis_getrpcbyname_r (const char *name, struct rpcent *rpc,
return NSS_STATUS_UNAVAIL;
}
intern_t data = { NULL, NULL };
intern_t data = { NULL, NULL, 0 };
enum nss_status status = internal_nis_setrpcent (&data);
if (__builtin_expect (status != NSS_STATUS_SUCCESS, 0))
return status;

View File

@ -37,20 +37,6 @@
__libc_lock_define_initialized (static, lock)
struct response_t
{
struct response_t *next;
size_t size;
char mem[0];
};
typedef struct intern_t
{
struct response_t *start;
struct response_t *next;
size_t offset;
} intern_t;
static intern_t intern;
struct search_t
@ -65,63 +51,6 @@ struct search_t
int *errnop;
};
static int
saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
{
if (instatus != YP_TRUE)
return 1;
if (inkey && inkeylen > 0 && inval && invallen > 0)
{
struct response_t *bucket = intern.next;
if (__builtin_expect (bucket == NULL, 0))
{
#define MINSIZE 4096 - 4 * sizeof (void *)
const size_t minsize = MAX (MINSIZE, 2 * (invallen + 1));
bucket = malloc (sizeof (struct response_t) + minsize);
if (bucket == NULL)
/* We have no error code for out of memory. */
return 1;
bucket->next = NULL;
bucket->size = minsize;
intern.start = intern.next = bucket;
intern.offset = 0;
}
else if (__builtin_expect (invallen + 1 > bucket->size - intern.offset,
0))
{
/* We need a new (larger) buffer. */
const size_t newsize = 2 * MAX (bucket->size, invallen + 1);
struct response_t *newp = malloc (sizeof (struct response_t)
+ newsize);
if (newp == NULL)
/* We have no error code for out of memory. */
return 1;
/* Mark the old bucket as full. */
bucket->size = intern.offset;
newp->next = NULL;
newp->size = newsize;
bucket = intern.next = bucket->next = newp;
intern.offset = 0;
}
char *p = mempcpy (&bucket->mem[intern.offset], inval, invallen);
if (__builtin_expect (p[-1] != '\0', 0))
{
*p = '\0';
++invallen;
}
intern.offset += invallen;
}
return 0;
}
static int
dosearch (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
@ -220,8 +149,8 @@ internal_nis_setservent (void)
internal_nis_endservent ();
ypcb.foreach = saveit;
ypcb.data = NULL;
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) &intern;
status = yperr2nss (yp_all (domainname, "services.byname", &ypcb));
/* Mark the last buffer as full. */

View File

@ -68,8 +68,6 @@ static enum nss_status
internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen,
int *errnop)
{
struct parser_data *data = (void *) buffer;
char *domain;
if (__builtin_expect (yp_get_default_domain (&domain), 0))
return NSS_STATUS_UNAVAIL;