Background Info
I am trying to get the string of a user's username, with the only info provided about that user being their uid number. I have the uid as a result of a preceding call to fstat (and the uid is stored in a struct stat).
I need to get the username in a thread-safe manner, and so I am trying to use getpwuid_r(). According to the getpwuid (3) man page:
int getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer,
size_t bufsize, struct passwd **result);
The
getpwuid_r()function shall update thepasswdstructure pointed to bypwdand store a pointer to that structure at the location pointed to by result. The structure shall contain an entry from the user database with a matchinguid. Storage referenced by the structure is allocated from the memory provided with the buffer parameter, which isbufsizebytes in size. A call tosysconf(_SC_GETPW_R_SIZE_MAX)returns either −1 without changingerrnoor an initial value suggested for the size of this buffer. A null pointer shall be returned at the location pointed to by result on error or if the requested entry is not found.If successful, the
getpwuid_r()function shall return zero; otherwise, an error number shall be returned to indicate the error.
Problem Statement
Upon reading the man page example below, I am confused as to why they need to iterate, while increasing the size of the buffer, until the buffer can hold its information.
I am under the presumption that the buffer holds the struct passwd pwd - considering this, why can't we just set buffer = (void *) malloc(getsize(struct passwd)) and bufsize = sizeof(struct passwd)?
long int initlen = sysconf(_SC_GETPW_R_SIZE_MAX);
size_t len;
if (initlen == −1)
/* Default initial length. */
len = 1024;
else
len = (size_t) initlen;
struct passwd result;
struct passwd *resultp;
char *buffer = malloc(len);
if (buffer == NULL)
...handle error...
int e;
while ((e = getpwuid_r(42, &result, buffer, len, &resultp)) == ERANGE)
{
size_t newlen = 2 * len;
if (newlen < len)
...handle error...
len = newlen;
char *newbuffer = realloc(buffer, len);
if (newbuffer == NULL)
...handle error...
buffer = newbuffer;
}
if (e != 0)
...handle error...
free (buffer);
Is there something I'm not understanding about how this function sets the data within pwd? Perhaps I don't fully understand how the struct passwd we are setting is related to the buffer space.