diff options
author | nkozlovskiy <nmk@ydb.tech> | 2023-12-06 16:48:03 +0300 |
---|---|---|
committer | nkozlovskiy <nmk@ydb.tech> | 2023-12-06 18:52:21 +0300 |
commit | 0856c44f0dac5a4dede7c44c16ba411f13b573ae (patch) | |
tree | a4b0833f45ffada5db15b14cb0b02dd20f747eb0 /contrib/go/_std_1.21/src | |
parent | 86f8b110c17767a66b011d38c1488230b41a1738 (diff) | |
download | ydb-0856c44f0dac5a4dede7c44c16ba411f13b573ae.tar.gz |
ydb-oss: add some go depends
Diffstat (limited to 'contrib/go/_std_1.21/src')
-rw-r--r-- | contrib/go/_std_1.21/src/net/cgo_stub.go | 40 | ||||
-rw-r--r-- | contrib/go/_std_1.21/src/os/user/listgroups_unix.go | 109 | ||||
-rw-r--r-- | contrib/go/_std_1.21/src/os/user/lookup_stubs.go | 83 | ||||
-rw-r--r-- | contrib/go/_std_1.21/src/os/user/lookup_unix.go | 234 |
4 files changed, 466 insertions, 0 deletions
diff --git a/contrib/go/_std_1.21/src/net/cgo_stub.go b/contrib/go/_std_1.21/src/net/cgo_stub.go new file mode 100644 index 0000000000..b26b11af8b --- /dev/null +++ b/contrib/go/_std_1.21/src/net/cgo_stub.go @@ -0,0 +1,40 @@ +// Copyright 2011 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. + +// This file holds stub versions of the cgo functions called on Unix systems. +// We build this file: +// - if using the netgo build tag on a Unix system +// - on a Unix system without the cgo resolver functions +// (Darwin always provides the cgo functions, in cgo_unix_syscall.go) +// - on wasip1, where cgo is never available + +//go:build (netgo && unix) || (unix && !cgo && !darwin) || wasip1 + +package net + +import "context" + +// cgoAvailable set to false to indicate that the cgo resolver +// is not available on this system. +const cgoAvailable = false + +func cgoLookupHost(ctx context.Context, name string) (addrs []string, err error) { + panic("cgo stub: cgo not available") +} + +func cgoLookupPort(ctx context.Context, network, service string) (port int, err error) { + panic("cgo stub: cgo not available") +} + +func cgoLookupIP(ctx context.Context, network, name string) (addrs []IPAddr, err error) { + panic("cgo stub: cgo not available") +} + +func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error, completed bool) { + panic("cgo stub: cgo not available") +} + +func cgoLookupPTR(ctx context.Context, addr string) (ptrs []string, err error) { + panic("cgo stub: cgo not available") +} diff --git a/contrib/go/_std_1.21/src/os/user/listgroups_unix.go b/contrib/go/_std_1.21/src/os/user/listgroups_unix.go new file mode 100644 index 0000000000..67bd8a776e --- /dev/null +++ b/contrib/go/_std_1.21/src/os/user/listgroups_unix.go @@ -0,0 +1,109 @@ +// Copyright 2021 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 ((darwin || dragonfly || freebsd || (js && wasm) || wasip1 || (!android && linux) || netbsd || openbsd || solaris) && ((!cgo && !darwin) || osusergo)) || aix || illumos + +package user + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "os" + "strconv" +) + +func listGroupsFromReader(u *User, r io.Reader) ([]string, error) { + if u.Username == "" { + return nil, errors.New("user: list groups: empty username") + } + primaryGid, err := strconv.Atoi(u.Gid) + if err != nil { + return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid) + } + + userCommas := []byte("," + u.Username + ",") // ,john, + userFirst := userCommas[1:] // john, + userLast := userCommas[:len(userCommas)-1] // ,john + userOnly := userCommas[1 : len(userCommas)-1] // john + + // Add primary Gid first. + groups := []string{u.Gid} + + rd := bufio.NewReader(r) + done := false + for !done { + line, err := rd.ReadBytes('\n') + if err != nil { + if err == io.EOF { + done = true + } else { + return groups, err + } + } + + // Look for username in the list of users. If user is found, + // append the GID to the groups slice. + + // There's no spec for /etc/passwd or /etc/group, but we try to follow + // the same rules as the glibc parser, which allows comments and blank + // space at the beginning of a line. + line = bytes.TrimSpace(line) + if len(line) == 0 || line[0] == '#' || + // If you search for a gid in a row where the group + // name (the first field) starts with "+" or "-", + // glibc fails to find the record, and so should we. + line[0] == '+' || line[0] == '-' { + continue + } + + // Format of /etc/group is + // groupname:password:GID:user_list + // for example + // wheel:x:10:john,paul,jack + // tcpdump:x:72: + listIdx := bytes.LastIndexByte(line, ':') + if listIdx == -1 || listIdx == len(line)-1 { + // No commas, or empty group list. + continue + } + if bytes.Count(line[:listIdx], colon) != 2 { + // Incorrect number of colons. + continue + } + list := line[listIdx+1:] + // Check the list for user without splitting or copying. + if !(bytes.Equal(list, userOnly) || bytes.HasPrefix(list, userFirst) || bytes.HasSuffix(list, userLast) || bytes.Contains(list, userCommas)) { + continue + } + + // groupname:password:GID + parts := bytes.Split(line[:listIdx], colon) + if len(parts) != 3 || len(parts[0]) == 0 { + continue + } + gid := string(parts[2]) + // Make sure it's numeric and not the same as primary GID. + numGid, err := strconv.Atoi(gid) + if err != nil || numGid == primaryGid { + continue + } + + groups = append(groups, gid) + } + + return groups, nil +} + +func listGroups(u *User) ([]string, error) { + f, err := os.Open(groupFile) + if err != nil { + return nil, err + } + defer f.Close() + + return listGroupsFromReader(u, f) +} diff --git a/contrib/go/_std_1.21/src/os/user/lookup_stubs.go b/contrib/go/_std_1.21/src/os/user/lookup_stubs.go new file mode 100644 index 0000000000..89dfe455b5 --- /dev/null +++ b/contrib/go/_std_1.21/src/os/user/lookup_stubs.go @@ -0,0 +1,83 @@ +// Copyright 2011 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 && !windows && !plan9) || android || (osusergo && !windows && !plan9) + +package user + +import ( + "fmt" + "os" + "runtime" + "strconv" +) + +var ( + // unused variables (in this implementation) + // modified during test to exercise code paths in the cgo implementation. + userBuffer = 0 + groupBuffer = 0 +) + +func current() (*User, error) { + uid := currentUID() + // $USER and /etc/passwd may disagree; prefer the latter if we can get it. + // See issue 27524 for more information. + u, err := lookupUserId(uid) + if err == nil { + return u, nil + } + + homeDir, _ := os.UserHomeDir() + u = &User{ + Uid: uid, + Gid: currentGID(), + Username: os.Getenv("USER"), + Name: "", // ignored + HomeDir: homeDir, + } + // On Android, return a dummy user instead of failing. + switch runtime.GOOS { + case "android": + if u.Uid == "" { + u.Uid = "1" + } + if u.Username == "" { + u.Username = "android" + } + } + // cgo isn't available, but if we found the minimum information + // without it, use it: + if u.Uid != "" && u.Username != "" && u.HomeDir != "" { + return u, nil + } + var missing string + if u.Username == "" { + missing = "$USER" + } + if u.HomeDir == "" { + if missing != "" { + missing += ", " + } + missing += "$HOME" + } + return u, fmt.Errorf("user: Current requires cgo or %s set in environment", missing) +} + +func currentUID() string { + if id := os.Getuid(); id >= 0 { + return strconv.Itoa(id) + } + // Note: Windows returns -1, but this file isn't used on + // Windows anyway, so this empty return path shouldn't be + // used. + return "" +} + +func currentGID() string { + if id := os.Getgid(); id >= 0 { + return strconv.Itoa(id) + } + return "" +} diff --git a/contrib/go/_std_1.21/src/os/user/lookup_unix.go b/contrib/go/_std_1.21/src/os/user/lookup_unix.go new file mode 100644 index 0000000000..a4308269e0 --- /dev/null +++ b/contrib/go/_std_1.21/src/os/user/lookup_unix.go @@ -0,0 +1,234 @@ +// 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 ((unix && !android) || (js && wasm) || wasip1) && ((!cgo && !darwin) || osusergo) + +package user + +import ( + "bufio" + "bytes" + "errors" + "io" + "os" + "strconv" + "strings" +) + +// lineFunc returns a value, an error, or (nil, nil) to skip the row. +type lineFunc func(line []byte) (v any, err error) + +// readColonFile parses r as an /etc/group or /etc/passwd style file, running +// fn for each row. readColonFile returns a value, an error, or (nil, nil) if +// the end of the file is reached without a match. +// +// readCols is the minimum number of colon-separated fields that will be passed +// to fn; in a long line additional fields may be silently discarded. +func readColonFile(r io.Reader, fn lineFunc, readCols int) (v any, err error) { + rd := bufio.NewReader(r) + + // Read the file line-by-line. + for { + var isPrefix bool + var wholeLine []byte + + // Read the next line. We do so in chunks (as much as reader's + // buffer is able to keep), check if we read enough columns + // already on each step and store final result in wholeLine. + for { + var line []byte + line, isPrefix, err = rd.ReadLine() + + if err != nil { + // We should return (nil, nil) if EOF is reached + // without a match. + if err == io.EOF { + err = nil + } + return nil, err + } + + // Simple common case: line is short enough to fit in a + // single reader's buffer. + if !isPrefix && len(wholeLine) == 0 { + wholeLine = line + break + } + + wholeLine = append(wholeLine, line...) + + // Check if we read the whole line (or enough columns) + // already. + if !isPrefix || bytes.Count(wholeLine, []byte{':'}) >= readCols { + break + } + } + + // There's no spec for /etc/passwd or /etc/group, but we try to follow + // the same rules as the glibc parser, which allows comments and blank + // space at the beginning of a line. + wholeLine = bytes.TrimSpace(wholeLine) + if len(wholeLine) == 0 || wholeLine[0] == '#' { + continue + } + v, err = fn(wholeLine) + if v != nil || err != nil { + return + } + + // If necessary, skip the rest of the line + for ; isPrefix; _, isPrefix, err = rd.ReadLine() { + if err != nil { + // We should return (nil, nil) if EOF is reached without a match. + if err == io.EOF { + err = nil + } + return nil, err + } + } + } +} + +func matchGroupIndexValue(value string, idx int) lineFunc { + var leadColon string + if idx > 0 { + leadColon = ":" + } + substr := []byte(leadColon + value + ":") + return func(line []byte) (v any, err error) { + if !bytes.Contains(line, substr) || bytes.Count(line, colon) < 3 { + return + } + // wheel:*:0:root + parts := strings.SplitN(string(line), ":", 4) + if len(parts) < 4 || parts[0] == "" || parts[idx] != value || + // If the file contains +foo and you search for "foo", glibc + // returns an "invalid argument" error. Similarly, if you search + // for a gid for a row where the group name starts with "+" or "-", + // glibc fails to find the record. + parts[0][0] == '+' || parts[0][0] == '-' { + return + } + if _, err := strconv.Atoi(parts[2]); err != nil { + return nil, nil + } + return &Group{Name: parts[0], Gid: parts[2]}, nil + } +} + +func findGroupId(id string, r io.Reader) (*Group, error) { + if v, err := readColonFile(r, matchGroupIndexValue(id, 2), 3); err != nil { + return nil, err + } else if v != nil { + return v.(*Group), nil + } + return nil, UnknownGroupIdError(id) +} + +func findGroupName(name string, r io.Reader) (*Group, error) { + if v, err := readColonFile(r, matchGroupIndexValue(name, 0), 3); err != nil { + return nil, err + } else if v != nil { + return v.(*Group), nil + } + return nil, UnknownGroupError(name) +} + +// returns a *User for a row if that row's has the given value at the +// given index. +func matchUserIndexValue(value string, idx int) lineFunc { + var leadColon string + if idx > 0 { + leadColon = ":" + } + substr := []byte(leadColon + value + ":") + return func(line []byte) (v any, err error) { + if !bytes.Contains(line, substr) || bytes.Count(line, colon) < 6 { + return + } + // kevin:x:1005:1006::/home/kevin:/usr/bin/zsh + parts := strings.SplitN(string(line), ":", 7) + if len(parts) < 6 || parts[idx] != value || parts[0] == "" || + parts[0][0] == '+' || parts[0][0] == '-' { + return + } + if _, err := strconv.Atoi(parts[2]); err != nil { + return nil, nil + } + if _, err := strconv.Atoi(parts[3]); err != nil { + return nil, nil + } + u := &User{ + Username: parts[0], + Uid: parts[2], + Gid: parts[3], + Name: parts[4], + HomeDir: parts[5], + } + // 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." + u.Name, _, _ = strings.Cut(u.Name, ",") + return u, nil + } +} + +func findUserId(uid string, r io.Reader) (*User, error) { + i, e := strconv.Atoi(uid) + if e != nil { + return nil, errors.New("user: invalid userid " + uid) + } + if v, err := readColonFile(r, matchUserIndexValue(uid, 2), 6); err != nil { + return nil, err + } else if v != nil { + return v.(*User), nil + } + return nil, UnknownUserIdError(i) +} + +func findUsername(name string, r io.Reader) (*User, error) { + if v, err := readColonFile(r, matchUserIndexValue(name, 0), 6); err != nil { + return nil, err + } else if v != nil { + return v.(*User), nil + } + return nil, UnknownUserError(name) +} + +func lookupGroup(groupname string) (*Group, error) { + f, err := os.Open(groupFile) + if err != nil { + return nil, err + } + defer f.Close() + return findGroupName(groupname, f) +} + +func lookupGroupId(id string) (*Group, error) { + f, err := os.Open(groupFile) + if err != nil { + return nil, err + } + defer f.Close() + return findGroupId(id, f) +} + +func lookupUser(username string) (*User, error) { + f, err := os.Open(userFile) + if err != nil { + return nil, err + } + defer f.Close() + return findUsername(username, f) +} + +func lookupUserId(uid string) (*User, error) { + f, err := os.Open(userFile) + if err != nil { + return nil, err + } + defer f.Close() + return findUserId(uid, f) +} |