package getgr import ( "syscall" "unsafe" ) //#define _POSIX_SOURCE // for getgrnam_r(3) in grp.h //#include // for free(3) //#include // for sysconf(3) //#include // for getgrnam_r(3) //static char *strary(char **ary, unsigned int n) { return ary[n]; } import "C" type Gid uint type Group struct { Name string Passwd string Gid Gid Mem []string } func strary(c **C.char) (g []string) { g = make([]string, 0) for i := C.uint(0); true; i++ { cstr := C.strary(c, i) if cstr == nil { return } g = append(g, C.GoString(cstr)) } panic("not reached") } // A wrapper around C getgrnam_r func ByName(name string) (*Group, error) { nameC := C.CString(name) defer C.free(unsafe.Pointer(nameC)) buflen := C.sysconf(C._SC_GETGR_R_SIZE_MAX) if buflen < 1 { buflen = 1024 } buf := make([]byte, buflen) var grp C.struct_group var ret *C.struct_group for { success, errno := C.getgrnam_r(nameC, &grp, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(buflen), &ret) if success >= 0 { break } if errno == syscall.ERANGE { buflen += 256 buf = make([]byte, buflen) } else { return nil, errno } } if ret == nil { return nil, nil } return &Group{ Name: C.GoString(ret.gr_name), Passwd: C.GoString(ret.gr_passwd), Gid: Gid(ret.gr_gid), Mem: strary(ret.gr_mem), }, nil } // A wrapper around C getgrgid_r func ByGid(gid int32) (*Group, error) { gidC := C.__gid_t(gid) buflen := C.sysconf(C._SC_GETGR_R_SIZE_MAX) if buflen < 1 { buflen = 1024 } buf := make([]byte, buflen) var grp C.struct_group var ret *C.struct_group for { success, errno := C.getgrgid_r(gidC, &grp, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(buflen), &ret) if success >= 0 { break } if errno == syscall.ERANGE { buflen += 256 buf = make([]byte, buflen) } else { return nil, errno } } if ret == nil { return nil, nil } return &Group{ Name: C.GoString(ret.gr_name), Passwd: C.GoString(ret.gr_passwd), Gid: Gid(ret.gr_gid), Mem: strary(ret.gr_mem), }, nil }