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 lookupUnix(uid int, username string, lookupByName bool) (*User, error) { var pwd syscall.Passwd var result *syscall.Passwd // FIXME: Should let buf grow if necessary. const bufSize = 1024 buf := make([]byte, bufSize) if lookupByName { nameC := syscall.StringBytePtr(username) syscall.Entersyscall() rv := libc_getpwnam_r(nameC, &pwd, &buf[0], bufSize, &result) syscall.Exitsyscall() if rv != 0 { return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.GetErrno()) } if result == nil { return nil, UnknownUserError(username) } } else { syscall.Entersyscall() rv := libc_getpwuid_r(syscall.Uid_t(uid), &pwd, &buf[0], bufSize, &result) syscall.Exitsyscall() if rv != 0 { return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.GetErrno()) } if result == nil { return nil, UnknownUserIdError(uid) } } u := &User{ Uid: strconv.Itoa(int(pwd.Pw_uid)), Gid: strconv.Itoa(int(pwd.Pw_gid)), 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." if i := strings.Index(u.Name, ","); i >= 0 { u.Name = u.Name[:i] } return u, nil }