...
Run Format

Source file src/os/user/lookup_unix.go

     1	// Copyright 2011 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 darwin dragonfly freebsd !android,linux netbsd openbsd solaris
     6	// +build cgo
     7	
     8	package user
     9	
    10	import (
    11		"fmt"
    12		"runtime"
    13		"strconv"
    14		"strings"
    15		"syscall"
    16		"unsafe"
    17	)
    18	
    19	/*
    20	#cgo solaris CFLAGS: -D_POSIX_PTHREAD_SEMANTICS
    21	#include <unistd.h>
    22	#include <sys/types.h>
    23	#include <pwd.h>
    24	#include <stdlib.h>
    25	
    26	static int mygetpwuid_r(int uid, struct passwd *pwd,
    27		char *buf, size_t buflen, struct passwd **result) {
    28		return getpwuid_r(uid, pwd, buf, buflen, result);
    29	}
    30	
    31	static int mygetpwnam_r(const char *name, struct passwd *pwd,
    32		char *buf, size_t buflen, struct passwd **result) {
    33		return getpwnam_r(name, pwd, buf, buflen, result);
    34	}
    35	*/
    36	import "C"
    37	
    38	func current() (*User, error) {
    39		return lookupUnix(syscall.Getuid(), "", false)
    40	}
    41	
    42	func lookup(username string) (*User, error) {
    43		return lookupUnix(-1, username, true)
    44	}
    45	
    46	func lookupId(uid string) (*User, error) {
    47		i, e := strconv.Atoi(uid)
    48		if e != nil {
    49			return nil, e
    50		}
    51		return lookupUnix(i, "", false)
    52	}
    53	
    54	func lookupUnix(uid int, username string, lookupByName bool) (*User, error) {
    55		var pwd C.struct_passwd
    56		var result *C.struct_passwd
    57	
    58		var bufSize C.long
    59		if runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd" {
    60			// DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX
    61			// and just return -1.  So just use the same
    62			// size that Linux returns.
    63			bufSize = 1024
    64		} else {
    65			bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
    66			if bufSize <= 0 || bufSize > 1<<20 {
    67				return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize)
    68			}
    69		}
    70		buf := C.malloc(C.size_t(bufSize))
    71		defer C.free(buf)
    72		var rv C.int
    73		if lookupByName {
    74			nameC := C.CString(username)
    75			defer C.free(unsafe.Pointer(nameC))
    76			// mygetpwnam_r is a wrapper around getpwnam_r to avoid
    77			// passing a size_t to getpwnam_r, because for unknown
    78			// reasons passing a size_t to getpwnam_r doesn't work on
    79			// Solaris.
    80			rv = C.mygetpwnam_r(nameC,
    81				&pwd,
    82				(*C.char)(buf),
    83				C.size_t(bufSize),
    84				&result)
    85			if rv != 0 {
    86				return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.Errno(rv))
    87			}
    88			if result == nil {
    89				return nil, UnknownUserError(username)
    90			}
    91		} else {
    92			// mygetpwuid_r is a wrapper around getpwuid_r to
    93			// to avoid using uid_t because C.uid_t(uid) for
    94			// unknown reasons doesn't work on linux.
    95			rv = C.mygetpwuid_r(C.int(uid),
    96				&pwd,
    97				(*C.char)(buf),
    98				C.size_t(bufSize),
    99				&result)
   100			if rv != 0 {
   101				return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.Errno(rv))
   102			}
   103			if result == nil {
   104				return nil, UnknownUserIdError(uid)
   105			}
   106		}
   107		u := &User{
   108			Uid:      strconv.Itoa(int(pwd.pw_uid)),
   109			Gid:      strconv.Itoa(int(pwd.pw_gid)),
   110			Username: C.GoString(pwd.pw_name),
   111			Name:     C.GoString(pwd.pw_gecos),
   112			HomeDir:  C.GoString(pwd.pw_dir),
   113		}
   114		// The pw_gecos field isn't quite standardized.  Some docs
   115		// say: "It is expected to be a comma separated list of
   116		// personal data where the first item is the full name of the
   117		// user."
   118		if i := strings.Index(u.Name, ","); i >= 0 {
   119			u.Name = u.Name[:i]
   120		}
   121		return u, nil
   122	}
   123	

View as plain text