Code generated by cmd/cgo; DO NOT EDIT.
line /usr/local/Cellar/go/1.16.3/libexec/src/os/user/cgo_lookup_unix.go:1:1 Copyright 2011 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+build aix darwin dragonfly freebsd !android,linux netbsd openbsd solaris +build cgo,!osusergo

package user; import _cgo_unsafe 

import (
	
	
	
	
	
)
#cgo solaris CFLAGS: -D_POSIX_PTHREAD_SEMANTICS#include <unistd.h>#include <sys/types.h>#include <pwd.h>#include <grp.h>#include <stdlib.h>
static int mygetpwuid_r(int uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result) { return getpwuid_r(uid, pwd, buf, buflen, result);}
static int mygetpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result) { return getpwnam_r(name, pwd, buf, buflen, result);}
static int mygetgrgid_r(int gid, struct group *grp, char *buf, size_t buflen, struct group **result) { return getgrgid_r(gid, grp, buf, buflen, result);}
static int mygetgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result) { return getgrnam_r(name, grp, buf, buflen, result);}
import _ 

func current() (*User, error) {
	return lookupUnixUid(syscall.Getuid())
}

func lookupUser(username string) (*User, error) {
	var pwd  /*line :53:10*/_Ctype_struct_passwd /*line :53:25*/
	var result * /*line :54:14*/_Ctype_struct_passwd /*line :54:29*/
	nameC := make([]byte, len(username)+1)
	copy(nameC, username)

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

mygetpwnam_r is a wrapper around getpwnam_r to avoid passing a size_t to getpwnam_r, because for unknown reasons passing a size_t to getpwnam_r doesn't work on Solaris.
		return syscall.Errno(func() _Ctype_int{ var _cgo0 *_Ctype_char = /*line :66:39*/(*_Ctype_char)(unsafe.Pointer(&nameC[0])); _cgoBase1 := /*line :67:4*/&pwd; _cgo1 := _cgoBase1; var _cgo2 *_Ctype_char = /*line :68:4*/(*_Ctype_char)(buf.ptr); var _cgo3 _Ctype_size_t = _Ctype_size_t(buf.size); _cgoBase4 := /*line :70:4*/&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  /*line :90:10*/_Ctype_struct_passwd /*line :90:25*/
	var result * /*line :91:14*/_Ctype_struct_passwd /*line :91:29*/

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

mygetpwuid_r is a wrapper around getpwuid_r to avoid using uid_t because C.uid_t(uid) for unknown reasons doesn't work on linux.
		return syscall.Errno(func() _Ctype_int{ var _cgo0 _Ctype_int = _Ctype_int(uid); _cgoBase1 := /*line :100:4*/&pwd; _cgo1 := _cgoBase1; var _cgo2 *_Ctype_char = /*line :101:4*/(*_Ctype_char)(buf.ptr); var _cgo3 _Ctype_size_t = _Ctype_size_t(buf.size); _cgoBase4 := /*line :103:4*/&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 * /*line :114:21*/_Ctype_struct_passwd /*line :114:36*/) *User {
	u := &User{
		Uid:      strconv.FormatUint(uint64(pwd.pw_uid), 10),
		Gid:      strconv.FormatUint(uint64(pwd.pw_gid), 10),
		Username: ( /*line :118:13*/_Cfunc_GoString /*line :118:22*/)(pwd.pw_name),
		Name:     ( /*line :119:13*/_Cfunc_GoString /*line :119:22*/)(pwd.pw_gecos),
		HomeDir:  ( /*line :120:13*/_Cfunc_GoString /*line :120:22*/)(pwd.pw_dir),
The pw_gecos field isn't quite standardized. Some docs say: "It is expected to be a comma separated list of personal data where the first item is the full name of the user."
	if i := strings.Index(u.Name, ","); i >= 0 {
		u.Name = u.Name[:i]
	}
	return u
}

func lookupGroup(groupname string) (*Group, error) {
	var grp  /*line :133:10*/_Ctype_struct_group /*line :133:24*/
	var result * /*line :134:14*/_Ctype_struct_group /*line :134:28*/

	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 = /*line :142:39*/(*_Ctype_char)(unsafe.Pointer(&cname[0])); _cgoBase1 := /*line :143:4*/&grp; _cgo1 := _cgoBase1; var _cgo2 *_Ctype_char = /*line :144:4*/(*_Ctype_char)(buf.ptr); var _cgo3 _Ctype_size_t = _Ctype_size_t(buf.size); _cgoBase4 := /*line :146:4*/&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  /*line :166:10*/_Ctype_struct_group /*line :166:24*/
	var result * /*line :167:14*/_Ctype_struct_group /*line :167:28*/

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

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.
		return syscall.Errno(func() _Ctype_int{ var _cgo0 _Ctype_int = _Ctype_int(gid); _cgoBase1 := /*line :176:4*/&grp; _cgo1 := _cgoBase1; var _cgo2 *_Ctype_char = /*line :177:4*/(*_Ctype_char)(buf.ptr); var _cgo3 _Ctype_size_t = _Ctype_size_t(buf.size); _cgoBase4 := /*line :179:4*/&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 * /*line :190:22*/_Ctype_struct_group /*line :190:36*/) *Group {
	g := &Group{
		Gid:  strconv.Itoa(int(grp.gr_gid)),
		Name: ( /*line :193:9*/_Cfunc_GoString /*line :193:18*/)(grp.gr_name),
	}
	return g
}

type bufferKind  /*line :198:17*/_Ctype_int /*line :198:22*/

const (
	userBuffer  = bufferKind(( /*line :201:27*/_Ciconst__SC_GETPW_R_SIZE_MAX /*line :201:48*/))
	groupBuffer = bufferKind(( /*line :202:27*/_Ciconst__SC_GETGR_R_SIZE_MAX /*line :202:48*/))
)

func (k bufferKind) initialSize()  /*line :205:35*/_Ctype_size_t /*line :205:43*/ {
	sz := ( /*line :206:8*/_Cfunc_sysconf /*line :206:16*/)( /*line :206:18*/_Ctype_int /*line :206:23*/(k))
DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX. Additionally, not all Linux systems have it, either. For example, the musl libc returns -1.
		return 1024
	}
Truncate. If this truly isn't enough, retryWithBuffer will error on the first run.
		return maxBufferSize
	}
	return  /*line :217:9*/_Ctype_size_t /*line :217:17*/(sz)
}

type memBuffer struct {
	ptr  unsafe.Pointer
	size  /*line :222:7*/_Ctype_size_t /*line :222:15*/
}

func alloc(kind bufferKind) *memBuffer {
	sz := kind.initialSize()
	return &memBuffer{
		ptr:  ( /*line :228:9*/_Cfunc__CMalloc /*line :228:16*/)(sz),
		size: sz,
	}
}

func (mb *memBuffer) resize(newSize  /*line :233:37*/_Ctype_size_t /*line :233:45*/) {
	mb.ptr = func() _cgo_unsafe.Pointer{ _cgo0 := /*line :234:21*/mb.ptr; var _cgo1 _Ctype_size_t = /*line :234:29*/newSize; _cgoCheckPointer(_cgo0, nil); return _Cfunc_realloc(_cgo0, _cgo1); }()
	mb.size = newSize
}

func (mb *memBuffer) free() {
	func() { _cgo0 := /*line :239:9*/mb.ptr; _cgoCheckPointer(_cgo0, nil); _Cfunc_free(_cgo0); }()
}
retryWithBuffer repeatedly calls f(), increasing the size of the buffer each time, until f succeeds, fails with a non-ERANGE error, or the buffer exceeds a reasonable limit.
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
}
Because we can't use cgo in tests:
func structPasswdForNegativeTest()  /*line :268:36*/_Ctype_struct_passwd /*line :268:51*/ {
	sp :=  /*line :269:8*/_Ctype_struct_passwd /*line :269:23*/{}
	sp.pw_uid = 1<<32 - 2
	sp.pw_gid = 1<<32 - 3
	return sp