package user; import _cgo_unsafe
import (
)
import _
func current() (*User, error) {
return lookupUnixUid(syscall.Getuid())
}
func lookupUser(username string) (*User, error) {
var pwd _Ctype_struct_passwd
var result * _Ctype_struct_passwd
nameC := make([]byte, len(username)+1)
copy(nameC, username)
buf := alloc(userBuffer)
defer buf.free()
err := retryWithBuffer(buf, func() syscall.Errno {
return syscall.Errno(func() _Ctype_int{ var _cgo0 *_Ctype_char = (*_Ctype_char)(unsafe.Pointer(&nameC[0])); _cgoBase1 := &pwd; _cgo1 := _cgoBase1; var _cgo2 *_Ctype_char = (*_Ctype_char)(buf.ptr); var _cgo3 _Ctype_size_t = _Ctype_size_t(buf.size); _cgoBase4 := &result; _cgo4 := _cgoBase4; _cgoCheckPointer(_cgoBase1, 0 == 0); _cgoCheckPointer(_cgoBase4, 0 == 0); return _Cfunc_mygetpwnam_r(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4); }())
})
if err != nil {
return nil, fmt.Errorf("user: lookup username %s: %v", username, err)
}
if result == nil {
return nil, UnknownUserError(username)
}
return buildUser(&pwd), err
}
func lookupUserId(uid string) (*User, error) {
i, e := strconv.Atoi(uid)
if e != nil {
return nil, e
}
return lookupUnixUid(i)
}
func lookupUnixUid(uid int) (*User, error) {
var pwd _Ctype_struct_passwd
var result * _Ctype_struct_passwd
buf := alloc(userBuffer)
defer buf.free()
err := retryWithBuffer(buf, func() syscall.Errno {
return syscall.Errno(func() _Ctype_int{ var _cgo0 _Ctype_int = _Ctype_int(uid); _cgoBase1 := &pwd; _cgo1 := _cgoBase1; var _cgo2 *_Ctype_char = (*_Ctype_char)(buf.ptr); var _cgo3 _Ctype_size_t = _Ctype_size_t(buf.size); _cgoBase4 := &result; _cgo4 := _cgoBase4; _cgoCheckPointer(_cgoBase1, 0 == 0); _cgoCheckPointer(_cgoBase4, 0 == 0); return _Cfunc_mygetpwuid_r(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4); }())
})
if err != nil {
return nil, fmt.Errorf("user: lookup userid %d: %v", uid, err)
}
if result == nil {
return nil, UnknownUserIdError(uid)
}
return buildUser(&pwd), nil
}
func buildUser(pwd * _Ctype_struct_passwd ) *User {
u := &User{
Uid: strconv.FormatUint(uint64(pwd.pw_uid), 10),
Gid: strconv.FormatUint(uint64(pwd.pw_gid), 10),
Username: ( _Cfunc_GoString )(pwd.pw_name),
Name: ( _Cfunc_GoString )(pwd.pw_gecos),
HomeDir: ( _Cfunc_GoString )(pwd.pw_dir),
}
if i := strings.Index(u.Name, ","); i >= 0 {
u.Name = u.Name[:i]
}
return u
}
func lookupGroup(groupname string) (*Group, error) {
var grp _Ctype_struct_group
var result * _Ctype_struct_group
buf := alloc(groupBuffer)
defer buf.free()
cname := make([]byte, len(groupname)+1)
copy(cname, groupname)
err := retryWithBuffer(buf, func() syscall.Errno {
return syscall.Errno(func() _Ctype_int{ var _cgo0 *_Ctype_char = (*_Ctype_char)(unsafe.Pointer(&cname[0])); _cgoBase1 := &grp; _cgo1 := _cgoBase1; var _cgo2 *_Ctype_char = (*_Ctype_char)(buf.ptr); var _cgo3 _Ctype_size_t = _Ctype_size_t(buf.size); _cgoBase4 := &result; _cgo4 := _cgoBase4; _cgoCheckPointer(_cgoBase1, 0 == 0); _cgoCheckPointer(_cgoBase4, 0 == 0); return _Cfunc_mygetgrnam_r(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4); }())
})
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 lookupGroupId(gid string) (*Group, error) {
i, e := strconv.Atoi(gid)
if e != nil {
return nil, e
}
return lookupUnixGid(i)
}
func lookupUnixGid(gid int) (*Group, error) {
var grp _Ctype_struct_group
var result * _Ctype_struct_group
buf := alloc(groupBuffer)
defer buf.free()
err := retryWithBuffer(buf, func() syscall.Errno {
return syscall.Errno(func() _Ctype_int{ var _cgo0 _Ctype_int = _Ctype_int(gid); _cgoBase1 := &grp; _cgo1 := _cgoBase1; var _cgo2 *_Ctype_char = (*_Ctype_char)(buf.ptr); var _cgo3 _Ctype_size_t = _Ctype_size_t(buf.size); _cgoBase4 := &result; _cgo4 := _cgoBase4; _cgoCheckPointer(_cgoBase1, 0 == 0); _cgoCheckPointer(_cgoBase4, 0 == 0); return _Cfunc_mygetgrgid_r(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4); }())
})
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
}
func buildGroup(grp * _Ctype_struct_group ) *Group {
g := &Group{
Gid: strconv.Itoa(int(grp.gr_gid)),
Name: ( _Cfunc_GoString )(grp.gr_name),
}
return g
}
type bufferKind _Ctype_int
const (
userBuffer = bufferKind(( _Ciconst__SC_GETPW_R_SIZE_MAX ))
groupBuffer = bufferKind(( _Ciconst__SC_GETGR_R_SIZE_MAX ))
)
func (k bufferKind) initialSize() _Ctype_size_t {
sz := ( _Cfunc_sysconf )( _Ctype_int (k))
if sz == -1 {
return 1024
}
if !isSizeReasonable(int64(sz)) {
return maxBufferSize
}
return _Ctype_size_t (sz)
}
type memBuffer struct {
ptr unsafe.Pointer
size _Ctype_size_t
}
func alloc(kind bufferKind) *memBuffer {
sz := kind.initialSize()
return &memBuffer{
ptr: ( _Cfunc__CMalloc )(sz),
size: sz,
}
}
func (mb *memBuffer) resize(newSize _Ctype_size_t ) {
mb.ptr = func() _cgo_unsafe.Pointer{ _cgo0 := mb.ptr; var _cgo1 _Ctype_size_t = newSize; _cgoCheckPointer(_cgo0, nil); return _Cfunc_realloc(_cgo0, _cgo1); }()
mb.size = newSize
}
func (mb *memBuffer) free() {
func() { _cgo0 := mb.ptr; _cgoCheckPointer(_cgo0, nil); _Cfunc_free(_cgo0); }()
}
func retryWithBuffer(buf *memBuffer, f func() syscall.Errno) error {
for {
errno := f()
if errno == 0 {
return nil
} else if errno != syscall.ERANGE {
return errno
}
newSize := buf.size * 2
if !isSizeReasonable(int64(newSize)) {
return fmt.Errorf("internal buffer exceeds %d bytes", maxBufferSize)
}
buf.resize(newSize)
}
}
const maxBufferSize = 1 << 20
func isSizeReasonable(sz int64) bool {
return sz > 0 && sz <= maxBufferSize
}
func structPasswdForNegativeTest() _Ctype_struct_passwd {
sp := _Ctype_struct_passwd {}
sp.pw_uid = 1<<32 - 2
sp.pw_gid = 1<<32 - 3
return sp
}