// GroupId is an adaption from https://codereview.appspot.com/4589049. func GroupId(name string) (int, error) { var grp C.struct_group var result *C.struct_group bufSize := C.size_t(C.sysconf(C._SC_GETGR_R_SIZE_MAX)) buf := C.malloc(bufSize) if buf == nil { return -1, fmt.Errorf(gettext.Gettext("allocation failed")) } defer C.free(buf) // mygetgrgid_r is a wrapper around getgrgid_r to // to avoid using gid_t because C.gid_t(gid) for // unknown reasons doesn't work on linux. rv := C.getgrnam_r(C.CString(name), &grp, (*C.char)(buf), bufSize, &result) if rv != 0 { return -1, fmt.Errorf(gettext.Gettext("failed group lookup: %s"), syscall.Errno(rv)) } if result == nil { return -1, fmt.Errorf(gettext.Gettext("unknown group %s"), name) } return int(C.int(result.gr_gid)), nil }
func getgrnam(name string) (grp Group, err error) { var cgrp C.struct_group var result *C.struct_group nameC := C.CString(name) defer C.free(unsafe.Pointer(nameC)) bufSize := C.sysconf(C._SC_GETGR_R_SIZE_MAX) if bufSize <= 0 || bufSize > 1<<20 { return grp, fmt.Errorf("unreasonable C._SC_GETGR_R_SIZE_MAX %d", bufSize) } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) // getgrnam_r is harder to use (from cgo), but it is thread safe if _, err := C.getgrnam_r(nameC, &cgrp, (*C.char)(buf), C.size_t(bufSize), &result); err != nil { return grp, fmt.Errorf("getgrnam_r failed for %q: %v", name, err) } if result == nil { return grp, fmt.Errorf("group %q not found", name) } grp.Name = C.GoString(result.gr_name) grp.Passwd = C.GoString(result.gr_passwd) grp.Gid = uint(result.gr_gid) p := unsafe.Pointer(result.gr_mem) for p != nil && (*(**C.char)(p)) != nil { member := C.GoString((*(**C.char)(p))) grp.Mem = append(grp.Mem, member) p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(p)) } return grp, nil }
// TODO: properly attribute http://golang.org/src/pkg/os/user/lookup_unix.go (BSD-style: http://golang.org/LICENSE) func GetGidByName(name string) (gid int, err error) { var group C.struct_group var result *C.struct_group var bufSize C.long bufSize = C.sysconf(C._SC_GETGR_R_SIZE_MAX) if bufSize <= 0 || bufSize > 1<<20 { log.Fatalf("ERROR: unreasonable _SC_GETGR_R_SIZE_MAX of %d", bufSize) } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var returnValue C.int nameC := C.CString(config.Group) defer C.free(unsafe.Pointer(nameC)) returnValue = C.getgrnam_r(nameC, &group, (*C.char)(buf), C.size_t(bufSize), &result) if returnValue != 0 { return -1, fmt.Errorf("ERROR: error looking up group", name, syscall.Errno(returnValue)) } if result == nil { return -1, UnknownLookupError(name) } gid = int(result.gr_gid) return }
func lookup(gid int, groupname string, lookupByName bool) (*Group, error) { var ( grp C.struct_group result *C.struct_group ) var bufSize C.long if runtime.GOOS == "freebsd" { // FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX // and just returns -1. So just use the same // size that Linux returns bufSize = 1024 } else { bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX) if bufSize <= 0 || bufSize > 1<<20 { return nil, fmt.Errorf( "user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize) } } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var rv C.int if lookupByName { nameC := C.CString(groupname) defer C.free(unsafe.Pointer(nameC)) rv = C.getgrnam_r(nameC, &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf( "group: lookup groupname %s: %s", groupname, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupError(groupname) } } else { rv = C.mygetgrgid_r(C.int(gid), &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupid %d: %s", gid, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupIdError(gid) } } g := &Group{ Gid: strconv.Itoa(int(grp.gr_gid)), Name: C.GoString(grp.gr_name), Members: getMembers(grp), } return g, nil }
func lookupUnix(gid int, groupname string, lookupByName bool) (*Group, error) { var grp C.struct_group var result *C.struct_group var bufSize C.long if runtime.GOOS == "freebsd" { panic("Don't know how to deal with freebsd.") } else { bufSize = C.sysconf(C._SC_GETGR_R_SIZE_MAX) * 20 if bufSize <= 0 || bufSize > 1<<20 { return nil, fmt.Errorf("group: unreasonable _SC_GETGR_R_SIZE_MAX of %d", bufSize) } } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var rv C.int if lookupByName { nameC := C.CString(groupname) defer C.free(unsafe.Pointer(nameC)) rv = C.getgrnam_r(nameC, &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupname %s: %s", groupname, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupError(groupname) } } else { rv = C.getgrgid_r(C.__gid_t(gid), &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupid %d: %s", gid, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupIdError(gid) } } u := &Group{ Gid: strconv.Itoa(int(grp.gr_gid)), Groupname: C.GoString(grp.gr_name), } return u, nil }
func lookup(gid int, groupname string, lookupByName bool) (*Group, error) { var grp C.struct_group var result *C.struct_group var bufsize C.long bufsize = C.sysconf(C._SC_GETGR_R_SIZE_MAX) if bufsize == -1 { bufsize = 1024 } buf := C.malloc(C.size_t(bufsize)) defer C.free(buf) var rv C.int if lookupByName { CGroup := C.CString(groupname) defer C.free(unsafe.Pointer(CGroup)) rv = C.getgrnam_r(CGroup, &grp, (*C.char)(buf), C.size_t(bufsize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup group name %s: %s", groupname, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupError(groupname) } } else { rv = C.getgrgid_r(C.gid_t(gid), &grp, (*C.char)(buf), C.size_t(bufsize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup gid %d: %s", gid, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupIdError(gid) } } g := &Group{ Gid: int(grp.gr_gid), Name: C.GoString(grp.gr_name), Members: convert(grp.gr_mem), } return g, nil }
func lookupUnixGroup(gid int, groupname string, lookupByName bool, f func(*C.struct_group) *Group) (*Group, error) { var grp C.struct_group var result *C.struct_group buf, bufSize, err := allocBuffer(groupBuffer) if err != nil { return nil, err } defer C.free(buf) if lookupByName { nameC := C.CString(groupname) defer C.free(unsafe.Pointer(nameC)) rv := C.getgrnam_r(nameC, &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupname %s: %s", groupname, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupError(groupname) } } else { // mygetgrgid_r is a wrapper around getgrgid_r to // to avoid using gid_t because C.gid_t(gid) for // unknown reasons doesn't work on linux. rv := C.mygetgrgid_r(C.int(gid), &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupid %d: %s", gid, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupIDError(gid) } } g := f(&grp) return g, nil }
func lookupGroup(groupname string) (*Group, error) { var grp C.struct_group var result *C.struct_group buf := alloc(groupBuffer) defer buf.free() cname := C.CString(groupname) defer C.free(unsafe.Pointer(cname)) err := retryWithBuffer(buf, func() syscall.Errno { return syscall.Errno(C.getgrnam_r(cname, &grp, (*C.char)(buf.ptr), C.size_t(buf.size), &result)) }) if err != nil { return nil, fmt.Errorf("user: lookup groupname %s: %v", groupname, err) } if result == nil { return nil, UnknownGroupError(groupname) } return buildGroup(&grp), nil }
func lookupUnix(gid int, groupname string, lookupByName bool) (*Group, error) { var grp C.struct_group var result *C.struct_group var bufSize C.long if runtime.GOOS == "freebsd" { // FreeBSD doesn't have _SC_GETGR_R_SIZE_MAX // and just returns -1. So just use the same // size that Linux returns // TODO: Confirm this! bufSize = 1024 } else { bufSize = C.sysconf(C._SC_GETGR_R_SIZE_MAX) if bufSize <= 0 || bufSize > 1<<20 { return nil, fmt.Errorf("group: unreasonable _SC_GETGR_R_SIZE_MAX of %d", bufSize) } } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var rv C.int if lookupByName { nameC := C.CString(groupname) defer C.free(unsafe.Pointer(nameC)) rv = C.getgrnam_r(nameC, &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupname %s: %s", groupname, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupError(groupname) } } else { // mygetgrgid_r is a wrapper around getgrgid_r to // avoid using gid_t because C.gid_t(gid) for // unknown reasons doesn't work on linux. rv = C.mygetgrgid_r(C.int(gid), &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupid %d: %s", gid, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupIdError(gid) } } var members []string if grp.gr_mem != nil { members = make([]string, C.member_count(grp.gr_mem)) i := 0 for mem := grp.gr_mem; *mem != nil; mem = C.next_mem(mem) { members[i] = C.GoString(*mem) i += 1 } } else { members = make([]string, 0) } g := &Group{ Gid: strconv.Itoa(int(grp.gr_gid)), Name: C.GoString(grp.gr_name), Members: members, } return g, nil }
func lookupUnix(gid int, groupname string, lookupByName bool) (*Group, error) { var grp C.struct_group var result *C.struct_group var bufSize C.long if runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd" { // DragonFly and FreeBSD do not have _SC_GETGR_R_SIZE_MAX // and just return -1. So just use the same // size that Linux returns. bufSize = 1024 } else { bufSize = C.sysconf(C._SC_GETGR_R_SIZE_MAX) if bufSize <= 0 || bufSize > 1<<20 { return nil, fmt.Errorf("user: unreasonable _SC_GETGR_R_SIZE_MAX of %d", bufSize) } } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var rv C.int if lookupByName { nameC := C.CString(groupname) defer C.free(unsafe.Pointer(nameC)) rv = C.getgrnam_r(nameC, &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup group %s: %s", groupname, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupError(groupname) } } else { // mygetgrgid_r is a wrapper around getgrgid_r to // to avoid using uid_t because C.uid_t(uid) for // unknown reasons doesn't work on linux. rv = C.mygetgrgid_r(C.int(gid), &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("grp: lookup groupid %d: %s", gid, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupIdError(gid) } } members := make([]string, 0) for memptr := grp.gr_mem; *memptr != nil; memptr = (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(memptr)) + unsafe.Sizeof(*grp.gr_mem))) { members = append(members, C.GoString(*memptr)) } g := &Group{ Gid: strconv.Itoa(int(grp.gr_gid)), Name: C.GoString(grp.gr_name), Password: C.GoString(grp.gr_passwd), Members: members, } return g, nil }