c - 如何使用 getpwuid_r() 正确设置缓冲区和 bufsize?

标签 c linux struct operating-system filesystems

背景信息

我正在尝试获取用户用户名的字符串,提供的有关该用户的唯一信息是他们的 uid数字。我有uid由于之前调用 fstat (并且 uid 存储在 struct stat 中)。

我需要以线程安全的方式获取用户名,因此我尝试使用 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 是如何做到的我们设置的是和缓冲空间有关的。

最佳答案

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_passwdpw_gecos

getpwuidgetpwuid_r 之间的区别在于前者可能使用静态缓冲区来存储名称、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) 失败,您只需猜测字符串缓冲区应该有多大,并不断增加其大小,直到足够大。

1V7 ,当所有信息都在 /etc/passwd 中时,这个静态缓冲区只是/etc/passwd 相应行的副本,并在五个字符串字段中每个字段的末尾插入了一个 NUL。

关于c - 如何使用 getpwuid_r() 正确设置缓冲区和 bufsize?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47462890/

相关文章:

c - 在结构中,scanf 返回 var 地址而不是值

c - 为什么这个整数会自己递减?

linux - 使用 '&' 运行的具有 2 个函数的循环仍然串行运行它们

linux - 以低延迟访问 PCI 内存条 (Linux)

linux - 使用 bash 获取字符串的一部分

c# - 在结构上隐藏无参数构造函数

c - 链接两个具有相同函数签名的 lib 文件?

c - 在 OSX 上使用 GDB 检测堆栈损坏(在金丝雀值上设置观察点)

c - 套接字如何在 C 中工作?

c - 将结构传递给接受 void * 参数的函数的问题