// 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

package user

import (
	"fmt"
	"strconv"
	"strings"
	"syscall"
	"unsafe"
)

// bytePtrToString takes a NUL-terminated array of bytes and convert
// it to a Go string.
func bytePtrToString(p *byte) string {
	a := (*[10000]byte)(unsafe.Pointer(p))
	i := 0
	for a[i] != 0 {
		i++
	}
	return string(a[:i])
}

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

func lookupUser(username string) (*User, error) {
	var pwd syscall.Passwd
	var result *syscall.Passwd
	p := syscall.StringBytePtr(username)

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

	err := retryWithBuffer(buf, func() syscall.Errno {
		syscall.Entersyscall()
		rv := libc_getpwnam_r(p,
			&pwd,
			buf.ptr,
			buf.size,
			&result)
		syscall.Exitsyscall()
		if rv != 0 {
			return syscall.GetErrno()
		}
		return 0
	})
	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 syscall.Passwd
	var result *syscall.Passwd

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

	err := retryWithBuffer(buf, func() syscall.Errno {
		syscall.Entersyscall()
		rv := libc_getpwuid_r(syscall.Uid_t(uid),
			&pwd,
			buf.ptr,
			buf.size,
			&result)
		syscall.Exitsyscall()
		if rv != 0 {
			return syscall.GetErrno()
		}
		return 0
	})
	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 *syscall.Passwd) *User {
	u := &User{
		Uid:      strconv.Itoa(int(pwd.Pw_uid)),
		Gid:      strconv.Itoa(int(pwd.Pw_gid)),
		Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
		Name:     bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
		HomeDir:  bytePtrToString((*byte)(unsafe.Pointer(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 currentGroup() (*Group, error) {
	return lookupUnixGid(syscall.Getgid())
}

func lookupGroup(groupname string) (*Group, error) {
	var grp syscall.Group
	var result *syscall.Group

	buf := alloc(groupBuffer)
	defer buf.free()
	p := syscall.StringBytePtr(groupname)

	err := retryWithBuffer(buf, func() syscall.Errno {
		syscall.Entersyscall()
		rv := libc_getgrnam_r(p,
			&grp,
			buf.ptr,
			buf.size,
			&result)
		syscall.Exitsyscall()
		if rv != 0 {
			return syscall.GetErrno()
		}
		return 0
	})
	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 syscall.Group
	var result *syscall.Group

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

	err := retryWithBuffer(buf, func() syscall.Errno {
		syscall.Entersyscall()
		rv := libc_getgrgid_r(syscall.Gid_t(gid),
			&grp,
			buf.ptr,
			buf.size,
			&result)
		syscall.Exitsyscall()
		if rv != 0 {
			return syscall.GetErrno()
		}
		return 0
	})
	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 *syscall.Group) *Group {
	g := &Group{
		Gid:  strconv.Itoa(int(grp.Gr_gid)),
		Name: bytePtrToString((*byte)(unsafe.Pointer(grp.Gr_name))),
	}
	return g
}

type bufferKind int

const (
	userBuffer  = bufferKind(syscall.SC_GETPW_R_SIZE_MAX)
	groupBuffer = bufferKind(syscall.SC_GETGR_R_SIZE_MAX)
)

func (k bufferKind) initialSize() syscall.Size_t {
	sz, _ := syscall.Sysconf(int(k))
	if sz == -1 {
		// 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
	}
	if !isSizeReasonable(int64(sz)) {
		// Truncate.  If this truly isn't enough, retryWithBuffer will error on the first run.
		return maxBufferSize
	}
	return syscall.Size_t(sz)
}

type memBuffer struct {
	ptr  *byte
	size syscall.Size_t
}

func alloc(kind bufferKind) *memBuffer {
	sz := kind.initialSize()
	b := make([]byte, sz)
	return &memBuffer{
		ptr:  &b[0],
		size: sz,
	}
}

func (mb *memBuffer) resize(newSize syscall.Size_t) {
	b := make([]byte, newSize)
	mb.ptr = &b[0]
	mb.size = newSize
}

func (mb *memBuffer) free() {
	mb.ptr = nil
}

// 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
}
