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

//go:build (aix || darwin || dragonfly || freebsd || hurd || (!android && linux) || netbsd || openbsd || solaris) && cgo && !osusergo

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 {
	if p == nil {
		return ""
	}
	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.FormatUint(uint64(pwd.Pw_uid), 10),
		Gid:      strconv.FormatUint(uint64(pwd.Pw_gid), 10),
		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."
	u.Name, _, _ = strings.Cut(u.Name, ",")
	return u
}

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
}

// Because we can't use cgo in tests:
func structPasswdForNegativeTest() syscall.Passwd {
	sp := syscall.Passwd{}
	sp.Pw_uid = 1<<32 - 2
	sp.Pw_gid = 1<<32 - 3
	return sp
}
