如何使用 getpwuid_r() 正确设置缓冲区和 bufsize?
How to properly set buffer and bufsize with getpwuid_r()?
背景信息
我正在尝试获取用户用户名的字符串,提供的有关该用户的唯一信息是他们的 uid
号码。由于先前调用 fstat
(并且 uid
存储在 struct stat
中,我得到了 uid
。
我需要以线程安全的方式获取用户名,因此我尝试使用 getpwuid_r()
。根据 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 the passwd
structure pointed
to by pwd
and 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 matching uid
. Storage referenced by the
structure is allocated from the memory provided with the buffer
parameter, which is bufsize
bytes in size. A call to
sysconf(_SC_GETPW_R_SIZE_MAX)
returns either −1 without changing
errno
or 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.
问题陈述
阅读下面的手册页示例后,我很困惑为什么他们需要迭代,同时增加缓冲区的大小,直到缓冲区可以容纳其信息。
我假设缓冲区包含 struct passwd pwd
- 考虑到这一点,为什么我们不能只设置 buffer = (void *) malloc(getsize(struct passwd))
和 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);
关于此函数如何在 pwd
中设置数据,我有什么不明白的地方吗?可能我不太明白我们设置的struct passwd
和bufferspace.
有什么关系
passwd
结构由 standard 定义,至少包含以下成员:
char *pw_name // User's login name.
uid_t pw_uid // Numerical user ID.
gid_t pw_gid // Numerical group ID.
char *pw_dir // Initial working directory.
char *pw_shell // Program to use as shell.
注意三个 char *
成员;他们指向位于结构之外的其他地方的存储。
许多实现将有两个更多的 char *
成员:pw_passwd
和 pw_gecos
.
getpwuid
和getpwuid_r
的区别在于前者可能使用静态缓冲区来存储name、passwd、dir、gecos和shell字符串1 - 以及 passwd
结构本身 - 而后者,因为它是可重入的,需要用户提供一个缓冲区来保存 struct passwd
和另一个缓冲区来保存字符串.
实际上,这两个函数共享很多 common code。
I am confused as to why they need to iterate, while increasing the size of the buffer, until the buffer can hold its information.
如果调用sysconf(_SC_GETPW_R_SIZE_MAX)
失败,你只需要猜测字符串的缓冲区应该有多大,并不断增加它的大小直到足够大。
1 在 V7 中,当所有信息都在 /etc/passwd
中时,此静态缓冲区只是 [=42] 相应行的副本=] 在五个字符串字段的每个末尾插入一个 NUL。
背景信息
我正在尝试获取用户用户名的字符串,提供的有关该用户的唯一信息是他们的 uid
号码。由于先前调用 fstat
(并且 uid
存储在 struct stat
中,我得到了 uid
。
我需要以线程安全的方式获取用户名,因此我尝试使用 getpwuid_r()
。根据 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 thepasswd
structure pointed to bypwd
and 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 isbufsize
bytes in size. A call tosysconf(_SC_GETPW_R_SIZE_MAX)
returns either −1 without changingerrno
or 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.
问题陈述
阅读下面的手册页示例后,我很困惑为什么他们需要迭代,同时增加缓冲区的大小,直到缓冲区可以容纳其信息。
我假设缓冲区包含 struct passwd pwd
- 考虑到这一点,为什么我们不能只设置 buffer = (void *) malloc(getsize(struct passwd))
和 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);
关于此函数如何在 pwd
中设置数据,我有什么不明白的地方吗?可能我不太明白我们设置的struct passwd
和bufferspace.
passwd
结构由 standard 定义,至少包含以下成员:
char *pw_name // User's login name.
uid_t pw_uid // Numerical user ID.
gid_t pw_gid // Numerical group ID.
char *pw_dir // Initial working directory.
char *pw_shell // Program to use as shell.
注意三个 char *
成员;他们指向位于结构之外的其他地方的存储。
许多实现将有两个更多的 char *
成员:pw_passwd
和 pw_gecos
.
getpwuid
和getpwuid_r
的区别在于前者可能使用静态缓冲区来存储name、passwd、dir、gecos和shell字符串1 - 以及 passwd
结构本身 - 而后者,因为它是可重入的,需要用户提供一个缓冲区来保存 struct passwd
和另一个缓冲区来保存字符串.
实际上,这两个函数共享很多 common code。
I am confused as to why they need to iterate, while increasing the size of the buffer, until the buffer can hold its information.
如果调用sysconf(_SC_GETPW_R_SIZE_MAX)
失败,你只需要猜测字符串的缓冲区应该有多大,并不断增加它的大小直到足够大。
1 在 V7 中,当所有信息都在 /etc/passwd
中时,此静态缓冲区只是 [=42] 相应行的副本=] 在五个字符串字段的每个末尾插入一个 NUL。