【问题标题】:How to properly set buffer and bufsize with getpwuid_r()?如何使用 getpwuid_r() 正确设置缓冲区和 bufsize?
【发布时间】:2018-05-07 20:32:27
【问题描述】:

背景资料

我正在尝试获取用户用户名的字符串,提供的关于该用户的唯一信息是他们的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);

getpwuid_r() 函数应更新指向的passwd 结构 通过pwd 并在该位置存储指向该结构的指针 结果指出。该结构应包含一个条目 具有匹配 uid 的用户数据库。引用的存储 结构是从缓冲区提供的内存中分配的 参数,大小为bufsize 字节。打电话给 sysconf(_SC_GETPW_R_SIZE_MAX) 返回任一 -1 而不改变 errno 或为此缓冲区大小建议的初始值。一种 空指针应返回结果指向的位置 出错或未找到请求的条目。

如果成功,getpwuid_r() 函数将返回零; 否则,将返回错误号以指示错误。



问题陈述

阅读下面的手册页示例后,我很困惑为什么他们需要迭代,同时增加缓冲区的大小,直到缓冲区可以保存其信息。

我假设缓冲区包含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和缓冲空间有什么关系。

【问题讨论】:

    标签: c linux struct operating-system filesystems


    【解决方案1】:

    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 的区别在于前者可以使用静态缓冲区来存储名称、密码、目录、gecos 和 shell 字符串1 - 以及 @ 987654332@ 结构本身 - 而后者,因为它是可重入的,需要用户提供一个缓冲区来保存 struct passwd 和另一个缓冲区来保存字符串。

    在实践中,这两个函数共享很多common code

    我很困惑为什么他们需要迭代,同时增加缓冲区的大小,直到缓冲区可以保存其信息。

    如果对sysconf(_SC_GETPW_R_SIZE_MAX) 的调用失败,您只需猜测字符串的缓冲区应该有多大,并不断增加其大小直到足够大。

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

    【讨论】:

      猜你喜欢
      • 2012-03-06
      • 2020-09-05
      • 2021-01-23
      • 2013-04-13
      • 1970-01-01
      • 2015-03-18
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多