Home | History | Annotate | Download | only in user
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build dragonfly darwin freebsd !android,linux netbsd openbsd
      6 
      7 package user
      8 
      9 import (
     10 	"fmt"
     11 	"strconv"
     12 	"unsafe"
     13 )
     14 
     15 /*
     16 #include <unistd.h>
     17 #include <sys/types.h>
     18 #include <stdlib.h>
     19 */
     20 import "C"
     21 
     22 func listGroups(u *User) ([]string, error) {
     23 	ug, err := strconv.Atoi(u.Gid)
     24 	if err != nil {
     25 		return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid)
     26 	}
     27 	userGID := C.gid_t(ug)
     28 	nameC := C.CString(u.Username)
     29 	defer C.free(unsafe.Pointer(nameC))
     30 
     31 	n := C.int(256)
     32 	gidsC := make([]C.gid_t, n)
     33 	rv := getGroupList(nameC, userGID, &gidsC[0], &n)
     34 	if rv == -1 {
     35 		// More than initial buffer, but now n contains the correct size.
     36 		const maxGroups = 2048
     37 		if n > maxGroups {
     38 			return nil, fmt.Errorf("user: list groups for %s: member of more than %d groups", u.Username, maxGroups)
     39 		}
     40 		gidsC = make([]C.gid_t, n)
     41 		rv := getGroupList(nameC, userGID, &gidsC[0], &n)
     42 		if rv == -1 {
     43 			return nil, fmt.Errorf("user: list groups for %s failed (changed groups?)", u.Username)
     44 		}
     45 	}
     46 	gidsC = gidsC[:n]
     47 	gids := make([]string, 0, n)
     48 	for _, g := range gidsC[:n] {
     49 		gids = append(gids, strconv.Itoa(int(g)))
     50 	}
     51 	return gids, nil
     52 }
     53