static int hadoop_group_info_fetch_nonreentrant(
      struct hadoop_group_info *ginfo, gid_t gid)
{
  struct group *group;
  int i, num_users = 0;
  char **g;

  do {
    errno = 0;
    group = getgrgid(gid);
  } while ((!group) && (errno == EINTR));
  if (!group) {
    return getgrgid_error_translate(errno);
  }
  ginfo->group.gr_name = strdup(group->gr_name);
  if (!ginfo->group.gr_name) {
    hadoop_group_info_clear(ginfo);
    return ENOMEM;
  }
  ginfo->group.gr_passwd = strdup(group->gr_passwd);
  if (!ginfo->group.gr_passwd) {
    hadoop_group_info_clear(ginfo);
    return ENOMEM;
  }
  ginfo->group.gr_gid = group->gr_gid;
  if (group->gr_mem) {
    for (g = group->gr_mem, num_users = 0;
         *g; g++) {
      num_users++;
    }
  }
  ginfo->group.gr_mem = calloc(num_users + 1, sizeof(char *));
  if (!ginfo->group.gr_mem) {
    hadoop_group_info_clear(ginfo);
    return ENOMEM;
  }
  for (i = 0; i < num_users; i++) {
    ginfo->group.gr_mem[i] = strdup(group->gr_mem[i]);
    if (!ginfo->group.gr_mem[i]) {
      hadoop_group_info_clear(ginfo);
      return ENOMEM;
    }
  }
  return 0;
}
void hadoop_group_info_free(struct hadoop_group_info *ginfo)
{
  if (!ginfo->buf_sz) {
    hadoop_group_info_clear(ginfo);
  } else {
    free(ginfo->buf);
  }
  free(ginfo);
}
int hadoop_group_info_fetch(struct hadoop_group_info *ginfo, gid_t gid)
{
  int ret;
  hadoop_group_info_clear(ginfo);

  if (!ginfo->buf_sz) {
    static pthread_mutex_t g_getgrnam_lock = PTHREAD_MUTEX_INITIALIZER;

    pthread_mutex_lock(&g_getgrnam_lock);
    ret = hadoop_group_info_fetch_nonreentrant(ginfo, gid);
    pthread_mutex_unlock(&g_getgrnam_lock);
    return ret;
  } else {
    return hadoop_group_info_fetch_reentrant(ginfo, gid);
  }
}
Exemple #4
0
int hadoop_group_info_fetch(struct hadoop_group_info *ginfo, gid_t gid)
{
  struct group *group;
  int ret; 
  size_t buf_sz;
  char *nbuf;

  hadoop_group_info_clear(ginfo);
  for (;;) {
    // On success, the following call returns 0 and group is set to non-NULL.
    group = NULL;
    ret = getgrgid_r(gid, &ginfo->group, ginfo->buf,
                       ginfo->buf_sz, &group);
    switch(ret) {
      case 0:
        if (!group) {
          // Not found.
          return ENOENT;
        }
        // Found.
        return 0;
      case EINTR:
        // EINTR: a signal was handled and this thread was allowed to continue.
        break;
      case ERANGE:
        // ERANGE: the buffer was not big enough.
        if (ginfo->buf_sz == MAX_GROUP_BUFFER_SIZE) {
          // Already tried with the max size.
          return ENOMEM;
        }
        buf_sz = ginfo->buf_sz * 2;
        if (buf_sz > MAX_GROUP_BUFFER_SIZE) {
          buf_sz = MAX_GROUP_BUFFER_SIZE;
        }
        nbuf = realloc(ginfo->buf, buf_sz);
        if (!nbuf) {
          return ENOMEM;
        }
        ginfo->buf = nbuf;
        ginfo->buf_sz = buf_sz;
        break;
      default:
        // Lookup failed.
        return getgrgid_error_translate(ret);
    }
  }
}