From b6f1fcb4f2d3cfb1eea95e9e0c6ae11f0659ba3a Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 7 Sep 2015 23:15:28 -0600 Subject: Pull the mucking with getgrnam into a getgr package. --- src/getgr/getgr.go | 103 +++++++++++++++++++++++++++++++++++++++ src/nshd/hackers_git/gid.go | 21 ++++++++ src/nshd/hackers_git/name2gid.go | 42 ---------------- 3 files changed, 124 insertions(+), 42 deletions(-) create mode 100644 src/getgr/getgr.go create mode 100644 src/nshd/hackers_git/gid.go delete mode 100644 src/nshd/hackers_git/name2gid.go (limited to 'src') diff --git a/src/getgr/getgr.go b/src/getgr/getgr.go new file mode 100644 index 0000000..5470b2c --- /dev/null +++ b/src/getgr/getgr.go @@ -0,0 +1,103 @@ +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 +} diff --git a/src/nshd/hackers_git/gid.go b/src/nshd/hackers_git/gid.go new file mode 100644 index 0000000..ff95309 --- /dev/null +++ b/src/nshd/hackers_git/gid.go @@ -0,0 +1,21 @@ +package hackers_git + +import "getgr" + +func name2gid(name string) int32 { + gr, err := getgr.ByName(name) + if gr == nil || err != nil { + return -1 + } else { + return int32(gr.Gid) + } +} + +func gid2name(gid int32) string { + gr, err := getgr.ByGid(gid) + if gr == nil || err != nil { + return "" + } else { + return gr.Name + } +} diff --git a/src/nshd/hackers_git/name2gid.go b/src/nshd/hackers_git/name2gid.go deleted file mode 100644 index c155d29..0000000 --- a/src/nshd/hackers_git/name2gid.go +++ /dev/null @@ -1,42 +0,0 @@ -package hackers_git - -import ( - "syscall" - "unsafe" -) - -//#define _XOPEN_SOURCE /* for getgrnam_r(3) in grp.h */ -//#include /* for free(3) */ -//#include /* for sysconf(3) */ -//#include /* for getgrnam_r(3) */ -import "C" - -func name2gid(name string) (gid int32) { - nameC := C.CString(name) - defer C.free(unsafe.Pointer(nameC)) - - gid = -1 - 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 - } - } - if ret != nil { - gid = int32(ret.gr_gid) - } - return -} -- cgit v1.2.2