func lookupUnixGid(gid int) (*Group, error) { var grp syscall.Group var result *syscall.Group buf := alloc(groupBuffer) defer buf.free() err := retryWithBuffer(buf, func() syscall.Errno { syscall.Entersyscall() rv := libc_getgrgid_r(syscall.Gid_t(gid), &grp, buf.ptr, buf.size, &result) syscall.Exitsyscall() if rv != 0 { return syscall.GetErrno() } return 0 }) if err != nil { return nil, fmt.Errorf("user: lookup groupid %d: %v", gid, err) } if result == nil { return nil, UnknownGroupIdError(strconv.Itoa(gid)) } return buildGroup(&grp), nil }
func listGroups(u *User) ([]string, error) { ug, err := strconv.Atoi(u.Gid) if err != nil { return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid) } userGID := syscall.Gid_t(ug) nameC, err := syscall.BytePtrFromString(u.Username) if err != nil { return nil, fmt.Errorf("user: invalid user name %q: %v", strconv.Quote(u.Username), err) } n := int32(256) gidsC := make([]syscall.Gid_t, n) syscall.Entersyscall() rv := libc_getgrouplist(nameC, userGID, &gidsC[0], &n) syscall.Exitsyscall() if rv == -1 { // More than initial buffer, but now n contains the correct size. const maxGroups = 2048 if n > maxGroups { return nil, fmt.Errorf("user: list groups for %s: member of more than %d groups", u.Username, maxGroups) } gidsC = make([]syscall.Gid_t, n) syscall.Entersyscall() rv := libc_getgrouplist(nameC, userGID, &gidsC[0], &n) syscall.Exitsyscall() if rv == -1 { return nil, fmt.Errorf("user: list groups for %s failed (changed groups?)", u.Username) } } gidsC = gidsC[:n] gids := make([]string, 0, n) for _, g := range gidsC[:n] { gids = append(gids, strconv.Itoa(int(g))) } return gids, nil }