// Copyright 2016 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 (cgo || darwin) && !osusergo && (darwin || dragonfly || freebsd || (linux && !android) || netbsd || openbsd || (solaris && !illumos))

package user

import (
	
	
	
)

const maxGroups = 2048

func listGroups( *User) ([]string, error) {
	,  := strconv.Atoi(.Gid)
	if  != nil {
		return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", .Username, .Gid)
	}
	 := _C_gid_t()
	 := make([]byte, len(.Username)+1)
	copy(, .Username)

	 := _C_int(256)
	 := make([]_C_gid_t, )
	 := getGroupList((*_C_char)(unsafe.Pointer(&[0])), , &[0], &)
	if  == -1 {
		// Mac is the only Unix that does not set n properly when rv == -1, so
		// we need to use different logic for Mac vs. the other OS's.
		if  := groupRetry(.Username, , , &, &);  != nil {
			return nil, 
		}
	}
	 = [:]
	 := make([]string, 0, )
	for ,  := range [:] {
		 = append(, strconv.Itoa(int()))
	}
	return , nil
}

// groupRetry retries getGroupList with much larger size for n. The result is
// stored in gids.
func groupRetry( string,  []byte,  _C_gid_t,  *[]_C_gid_t,  *_C_int) error {
	// More than initial buffer, but now n contains the correct size.
	if * > maxGroups {
		return fmt.Errorf("user: %q is a member of more than %d groups", , maxGroups)
	}
	* = make([]_C_gid_t, *)
	 := getGroupList((*_C_char)(unsafe.Pointer(&[0])), , &(*)[0], )
	if  == -1 {
		return fmt.Errorf("user: list groups for %s failed", )
	}
	return nil
}