Exemplo n.º 1
0
// GroupName is an adaption from https://codereview.appspot.com/4589049.
func GroupName(gid int) (string, 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 "", 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.mygetgrgid_r(C.int(gid),
		&grp,
		(*C.char)(buf),
		bufSize,
		&result)

	if rv != 0 {
		return "", fmt.Errorf(gettext.Gettext("failed group lookup: %s"), syscall.Errno(rv))
	}

	if result == nil {
		return "", fmt.Errorf(gettext.Gettext("unknown group %s"), gid)
	}

	return C.GoString(result.gr_name), nil
}
Exemplo n.º 2
0
// Because Go is like... naaaaa, no groups aren't a thing!
// Based on Go's src/os/user/lookup_unix.go
func currentUserAndGroup() (*userAndGroup, error) {
	u, err := user.Current()
	if err != nil {
		return nil, err
	}
	gid, err := strconv.Atoi(u.Gid)
	if err != nil {
		return nil, err
	}

	var grp C.struct_group
	var result *C.struct_group
	buflen := C.sysconf(C._SC_GETPW_R_SIZE_MAX)
	if buflen <= 0 || buflen > 1<<20 {
		return nil, fmt.Errorf("unreasonable _SC_GETGR_R_SIZE_MAX of %d", buflen)
	}
	buf := C.malloc(C.size_t(buflen))
	defer C.free(buf)

	r := C.mygetgrgid_r(C.gid_t(gid), &grp,
		(*C.char)(buf),
		C.size_t(buflen),
		&result)
	if r != 0 {
		return nil, fmt.Errorf("lookup gid %d: %s", gid, syscall.Errno(r))
	}
	if result == nil {
		return nil, fmt.Errorf("lookup gid %d failed", gid)
	}

	return &userAndGroup{
		User:      u,
		Groupname: C.GoString(grp.gr_name),
	}, nil
}
Exemplo n.º 3
0
func lookupUnixGid(gid int) (*Group, error) {
	var grp C.struct_group
	var result *C.struct_group

	buf := alloc(groupBuffer)
	defer buf.free()

	err := retryWithBuffer(buf, func() syscall.Errno {
		// 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.
		return syscall.Errno(C.mygetgrgid_r(C.int(gid),
			&grp,
			(*C.char)(buf.ptr),
			C.size_t(buf.size),
			&result))
	})
	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
}
Exemplo n.º 4
0
func getGroupName(fi os.FileInfo) (string, error) {
	var rv C.int
	var grp C.struct_group
	var grpres *C.struct_group
	var bufSize C.long
	var result string

	bufSize = 1024
	buf := C.malloc(C.size_t(bufSize))
	defer C.free(buf)

	gid := fi.Sys().(*syscall.Stat_t).Gid

	rv = C.mygetgrgid_r(C.int(gid), &grp, (*C.char)(buf), C.size_t(bufSize), &grpres)
	if rv != 0 {
		return "", errors.New("Could not read groupname")
	}

	if grpres != nil {
		result = C.GoString(grp.gr_name)
	} else {
		return "", errors.New("Could not convert groupname")
	}
	return result, nil
}
Exemplo n.º 5
0
// LookupID looks up a group name based on its group ID.
func lookupUnixGroup(gid int, 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)

	// 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
}
Exemplo n.º 6
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
}
Exemplo n.º 7
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.mygetgrnam_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)
		}
	}
	u := &Group{
		Gid:       strconv.Itoa(int(grp.gr_gid)),
		Groupname: C.GoString(grp.gr_name),
	}
	return u, nil
}
Exemplo n.º 8
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
}
Exemplo n.º 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 == "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
}