Beispiel #1
0
// 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
}
Beispiel #2
0
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
}
Beispiel #3
0
// 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
}
Beispiel #4
0
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
}
Beispiel #5
0
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
}
Beispiel #6
0
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
}
Beispiel #7
0
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
}
Beispiel #8
0
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
}
Beispiel #9
0
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
}
Beispiel #10
0
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
}