Browse Source

ydb-oss: add some go depends

nkozlovskiy 1 year ago
parent
commit
0856c44f0d

+ 40 - 0
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")
+}

+ 109 - 0
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)
+}

+ 83 - 0
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 ""
+}

+ 234 - 0
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)
+}