in internal/util/util.go [99:150]
func getUIDandGID(username string) (uid int, gid int, err error) {
var uidstr, gidstr string
// Preference is user.Lookup(), if it works
u, lookupErr := user.Lookup(username)
if lookupErr == nil {
// user.Lookup() was successful, use the returned UID/GID
uidstr = u.Uid
gidstr = u.Gid
} else {
// user.Lookup() has failed, second try by checking the DS cache
out, cmdErr := ExecuteCommand(context.Background(), []string{"dscacheutil", "-q", "user", "-a", "name", username}, "", []string{}, nil)
if cmdErr != nil {
// dscacheutil has failed with an error
return 0, 0, fmt.Errorf("dscacheutil: %w", cmdErr)
}
if len(out.Stdout) == 0 {
// dscacheutil returns nothing if user is not found
return 0, 0, fmt.Errorf("dscacheutil read user %q: %w", username, cmdErr)
} else {
// dscacheutil found user, extract the user info by keys
dscacheUserInfo := extractDSCacheUtilKeyValues([]byte(out.Stdout), []string{"gid", "uid"})
if len(dscacheUserInfo) == 0 {
return 0, 0, fmt.Errorf("dscacheutil read user %q: %w", username, cmdErr)
}
if gid, ok := dscacheUserInfo["gid"]; ok {
gidstr = gid
}
if uid, ok := dscacheUserInfo["uid"]; ok {
uidstr = uid
}
}
}
// make sure we actually resolved a user before carrying on
if uidstr == "" || gidstr == "" {
return 0, 0, fmt.Errorf("user %q: no user info", username)
}
// Parse read UID and GID to integers
uid, err = strconv.Atoi(uidstr)
if err != nil {
return 0, 0, fmt.Errorf("parse %q uid: %w", username, err)
}
gid, err = strconv.Atoi(gidstr)
if err != nil {
return 0, 0, fmt.Errorf("parse %q gid: %w", username, err)
}
return uid, gid, nil
}