mirror of
https://github.com/containers/skopeo.git
synced 2025-08-31 22:28:33 +00:00
vendor of containers/common
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
59
vendor/github.com/containers/common/libnetwork/types/const.go
generated
vendored
59
vendor/github.com/containers/common/libnetwork/types/const.go
generated
vendored
@@ -1,59 +0,0 @@
|
||||
package types
|
||||
|
||||
const (
|
||||
// BridgeNetworkDriver defines the bridge driver
|
||||
BridgeNetworkDriver = "bridge"
|
||||
// DefaultNetworkDriver is the default network type used
|
||||
DefaultNetworkDriver = BridgeNetworkDriver
|
||||
// MacVLANNetworkDriver defines the macvlan driver
|
||||
MacVLANNetworkDriver = "macvlan"
|
||||
// MacVLANNetworkDriver defines the macvlan driver
|
||||
IPVLANNetworkDriver = "ipvlan"
|
||||
|
||||
// IPAM drivers
|
||||
Driver = "driver"
|
||||
// HostLocalIPAMDriver store the ip locally in a db
|
||||
HostLocalIPAMDriver = "host-local"
|
||||
// DHCPIPAMDriver get subnet and ip from dhcp server
|
||||
DHCPIPAMDriver = "dhcp"
|
||||
// NoneIPAMDriver do not provide ipam management
|
||||
NoneIPAMDriver = "none"
|
||||
|
||||
// DefaultSubnet is the name that will be used for the default CNI network.
|
||||
DefaultNetworkName = "podman"
|
||||
// DefaultSubnet is the subnet that will be used for the default CNI network.
|
||||
DefaultSubnet = "10.88.0.0/16"
|
||||
|
||||
// valid macvlan driver mode values
|
||||
MacVLANModeBridge = "bridge"
|
||||
MacVLANModePrivate = "private"
|
||||
MacVLANModeVepa = "vepa"
|
||||
MacVLANModePassthru = "passthru"
|
||||
|
||||
// valid ipvlan driver modes
|
||||
IPVLANModeL2 = "l2"
|
||||
IPVLANModeL3 = "l3"
|
||||
IPVLANModeL3s = "l3s"
|
||||
|
||||
// valid network options
|
||||
VLANOption = "vlan"
|
||||
MTUOption = "mtu"
|
||||
ModeOption = "mode"
|
||||
IsolateOption = "isolate"
|
||||
MetricOption = "metric"
|
||||
NoDefaultRoute = "no_default_route"
|
||||
BclimOption = "bclim"
|
||||
)
|
||||
|
||||
type NetworkBackend string
|
||||
|
||||
const (
|
||||
CNI NetworkBackend = "cni"
|
||||
Netavark NetworkBackend = "netavark"
|
||||
)
|
||||
|
||||
// ValidMacVLANModes is the list of valid mode options for the macvlan driver
|
||||
var ValidMacVLANModes = []string{MacVLANModeBridge, MacVLANModePrivate, MacVLANModeVepa, MacVLANModePassthru}
|
||||
|
||||
// ValidIPVLANModes is the list of valid mode options for the ipvlan driver
|
||||
var ValidIPVLANModes = []string{IPVLANModeL2, IPVLANModeL3, IPVLANModeL3s}
|
30
vendor/github.com/containers/common/libnetwork/types/define.go
generated
vendored
30
vendor/github.com/containers/common/libnetwork/types/define.go
generated
vendored
@@ -1,30 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/storage/pkg/regexp"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoSuchNetwork indicates the requested network does not exist
|
||||
ErrNoSuchNetwork = errors.New("network not found")
|
||||
|
||||
// ErrInvalidArg indicates that an invalid argument was passed
|
||||
ErrInvalidArg = errors.New("invalid argument")
|
||||
|
||||
// ErrNetworkExists indicates that a network with the given name already
|
||||
// exists.
|
||||
ErrNetworkExists = errors.New("network already exists")
|
||||
|
||||
// NameRegex is a regular expression to validate names.
|
||||
// This must NOT be changed.
|
||||
NameRegex = regexp.Delayed("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$")
|
||||
// RegexError is thrown in presence of an invalid name.
|
||||
RegexError = fmt.Errorf("names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*: %w", ErrInvalidArg) // nolint:revive // This lint is new and we do not want to break the API.
|
||||
|
||||
// NotHexRegex is a regular expression to check if a string is
|
||||
// a hexadecimal string.
|
||||
NotHexRegex = regexp.Delayed(`[^0-9a-fA-F]`)
|
||||
)
|
339
vendor/github.com/containers/common/libnetwork/types/network.go
generated
vendored
339
vendor/github.com/containers/common/libnetwork/types/network.go
generated
vendored
@@ -1,339 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ContainerNetwork interface {
|
||||
// NetworkCreate will take a partial filled Network and fill the
|
||||
// missing fields. It creates the Network and returns the full Network.
|
||||
NetworkCreate(Network, *NetworkCreateOptions) (Network, error)
|
||||
// NetworkUpdate will take network name and ID and updates network DNS Servers.
|
||||
NetworkUpdate(nameOrID string, options NetworkUpdateOptions) error
|
||||
// NetworkRemove will remove the Network with the given name or ID.
|
||||
NetworkRemove(nameOrID string) error
|
||||
// NetworkList will return all known Networks. Optionally you can
|
||||
// supply a list of filter functions. Only if a network matches all
|
||||
// functions it is returned.
|
||||
NetworkList(...FilterFunc) ([]Network, error)
|
||||
// NetworkInspect will return the Network with the given name or ID.
|
||||
NetworkInspect(nameOrID string) (Network, error)
|
||||
|
||||
// Setup will setup the container network namespace. It returns
|
||||
// a map of StatusBlocks, the key is the network name.
|
||||
Setup(namespacePath string, options SetupOptions) (map[string]StatusBlock, error)
|
||||
// Teardown will teardown the container network namespace.
|
||||
Teardown(namespacePath string, options TeardownOptions) error
|
||||
|
||||
// Drivers will return the list of supported network drivers
|
||||
// for this interface.
|
||||
Drivers() []string
|
||||
|
||||
// DefaultNetworkName will return the default network name
|
||||
// for this interface.
|
||||
DefaultNetworkName() string
|
||||
|
||||
// NetworkInfo return the network information about backend type,
|
||||
// binary path, package version and so on.
|
||||
NetworkInfo() NetworkInfo
|
||||
}
|
||||
|
||||
// Network describes the Network attributes.
|
||||
type Network struct {
|
||||
// Name of the Network.
|
||||
Name string `json:"name"`
|
||||
// ID of the Network.
|
||||
ID string `json:"id"`
|
||||
// Driver for this Network, e.g. bridge, macvlan...
|
||||
Driver string `json:"driver"`
|
||||
// NetworkInterface is the network interface name on the host.
|
||||
NetworkInterface string `json:"network_interface,omitempty"`
|
||||
// Created contains the timestamp when this network was created.
|
||||
Created time.Time `json:"created,omitempty"`
|
||||
// Subnets to use for this network.
|
||||
Subnets []Subnet `json:"subnets,omitempty"`
|
||||
// Routes to use for this network.
|
||||
Routes []Route `json:"routes,omitempty"`
|
||||
// IPv6Enabled if set to true an ipv6 subnet should be created for this net.
|
||||
IPv6Enabled bool `json:"ipv6_enabled"`
|
||||
// Internal is whether the Network should not have external routes
|
||||
// to public or other Networks.
|
||||
Internal bool `json:"internal"`
|
||||
// DNSEnabled is whether name resolution is active for container on
|
||||
// this Network. Only supported with the bridge driver.
|
||||
DNSEnabled bool `json:"dns_enabled"`
|
||||
// List of custom DNS server for podman's DNS resolver at network level,
|
||||
// all the containers attached to this network will consider resolvers
|
||||
// configured at network level.
|
||||
NetworkDNSServers []string `json:"network_dns_servers,omitempty"`
|
||||
// Labels is a set of key-value labels that have been applied to the
|
||||
// Network.
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
// Options is a set of key-value options that have been applied to
|
||||
// the Network.
|
||||
Options map[string]string `json:"options,omitempty"`
|
||||
// IPAMOptions contains options used for the ip assignment.
|
||||
IPAMOptions map[string]string `json:"ipam_options,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkOptions for a given container.
|
||||
type NetworkUpdateOptions struct {
|
||||
// List of custom DNS server for podman's DNS resolver.
|
||||
// Priority order will be kept as defined by user in the configuration.
|
||||
AddDNSServers []string `json:"add_dns_servers,omitempty"`
|
||||
RemoveDNSServers []string `json:"remove_dns_servers,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkInfo contains the network information.
|
||||
type NetworkInfo struct {
|
||||
Backend NetworkBackend `json:"backend"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
DNS DNSNetworkInfo `json:"dns,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkInfo contains the DNS information.
|
||||
type DNSNetworkInfo struct {
|
||||
Version string `json:"version,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
}
|
||||
|
||||
// IPNet is used as custom net.IPNet type to add Marshal/Unmarshal methods.
|
||||
type IPNet struct {
|
||||
net.IPNet
|
||||
}
|
||||
|
||||
// ParseCIDR parse a string to IPNet
|
||||
func ParseCIDR(cidr string) (IPNet, error) {
|
||||
ip, subnet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
return IPNet{}, err
|
||||
}
|
||||
// convert to 4 bytes if ipv4
|
||||
ipv4 := ip.To4()
|
||||
if ipv4 != nil {
|
||||
ip = ipv4
|
||||
}
|
||||
subnet.IP = ip
|
||||
return IPNet{*subnet}, err
|
||||
}
|
||||
|
||||
func (n *IPNet) MarshalText() ([]byte, error) {
|
||||
return []byte(n.String()), nil
|
||||
}
|
||||
|
||||
func (n *IPNet) UnmarshalText(text []byte) error {
|
||||
subnet, err := ParseCIDR(string(text))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*n = subnet
|
||||
return nil
|
||||
}
|
||||
|
||||
// HardwareAddr is the same as net.HardwareAddr except
|
||||
// that it adds the json marshal/unmarshal methods.
|
||||
// This allows us to read the mac from a json string
|
||||
// and a byte array.
|
||||
// swagger:model MacAddress
|
||||
type HardwareAddr net.HardwareAddr
|
||||
|
||||
func (h *HardwareAddr) String() string {
|
||||
return (*net.HardwareAddr)(h).String()
|
||||
}
|
||||
|
||||
func (h HardwareAddr) MarshalText() ([]byte, error) {
|
||||
return []byte(h.String()), nil
|
||||
}
|
||||
|
||||
func (h *HardwareAddr) UnmarshalJSON(text []byte) error {
|
||||
if len(text) == 0 {
|
||||
*h = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// if the json string start with a quote we got a string
|
||||
// unmarshal the string and parse the mac from this string
|
||||
if string(text[0]) == `"` {
|
||||
var macString string
|
||||
err := json.Unmarshal(text, &macString)
|
||||
if err == nil {
|
||||
mac, err := net.ParseMAC(macString)
|
||||
if err == nil {
|
||||
*h = HardwareAddr(mac)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
// not a string or got an error fallback to the normal parsing
|
||||
mac := make(net.HardwareAddr, 0, 6)
|
||||
// use the standard json unmarshal for backwards compat
|
||||
err := json.Unmarshal(text, &mac)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*h = HardwareAddr(mac)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Subnet struct {
|
||||
// Subnet for this Network in CIDR form.
|
||||
// swagger:strfmt string
|
||||
Subnet IPNet `json:"subnet"`
|
||||
// Gateway IP for this Network.
|
||||
// swagger:strfmt string
|
||||
Gateway net.IP `json:"gateway,omitempty"`
|
||||
// LeaseRange contains the range where IP are leased. Optional.
|
||||
LeaseRange *LeaseRange `json:"lease_range,omitempty"`
|
||||
}
|
||||
|
||||
type Route struct {
|
||||
// Destination for this route in CIDR form.
|
||||
// swagger:strfmt string
|
||||
Destination IPNet `json:"destination"`
|
||||
// Gateway IP for this route.
|
||||
// swagger:strfmt string
|
||||
Gateway net.IP `json:"gateway"`
|
||||
// Metric for this route. Optional.
|
||||
Metric *uint32 `json:"metric,omitempty"`
|
||||
}
|
||||
|
||||
// LeaseRange contains the range where IP are leased.
|
||||
type LeaseRange struct {
|
||||
// StartIP first IP in the subnet which should be used to assign ips.
|
||||
// swagger:strfmt string
|
||||
StartIP net.IP `json:"start_ip,omitempty"`
|
||||
// EndIP last IP in the subnet which should be used to assign ips.
|
||||
// swagger:strfmt string
|
||||
EndIP net.IP `json:"end_ip,omitempty"`
|
||||
}
|
||||
|
||||
// StatusBlock contains the network information about a container
|
||||
// connected to one Network.
|
||||
type StatusBlock struct {
|
||||
// Interfaces contains the created network interface in the container.
|
||||
// The map key is the interface name.
|
||||
Interfaces map[string]NetInterface `json:"interfaces,omitempty"`
|
||||
// DNSServerIPs nameserver addresses which should be added to
|
||||
// the containers resolv.conf file.
|
||||
DNSServerIPs []net.IP `json:"dns_server_ips,omitempty"`
|
||||
// DNSSearchDomains search domains which should be added to
|
||||
// the containers resolv.conf file.
|
||||
DNSSearchDomains []string `json:"dns_search_domains,omitempty"`
|
||||
}
|
||||
|
||||
// NetInterface contains the settings for a given network interface.
|
||||
type NetInterface struct {
|
||||
// Subnets list of assigned subnets with their gateway.
|
||||
Subnets []NetAddress `json:"subnets,omitempty"`
|
||||
// MacAddress for this Interface.
|
||||
MacAddress HardwareAddr `json:"mac_address"`
|
||||
}
|
||||
|
||||
// NetAddress contains the ip address, subnet and gateway.
|
||||
type NetAddress struct {
|
||||
// IPNet of this NetAddress. Note that this is a subnet but it has to contain the
|
||||
// actual ip of the network interface and not the network address.
|
||||
IPNet IPNet `json:"ipnet"`
|
||||
// Gateway for the network. This can be empty if there is no gateway, e.g. internal network.
|
||||
Gateway net.IP `json:"gateway,omitempty"`
|
||||
}
|
||||
|
||||
// PerNetworkOptions are options which should be set on a per network basis.
|
||||
type PerNetworkOptions struct {
|
||||
// StaticIPs for this container. Optional.
|
||||
// swagger:type []string
|
||||
StaticIPs []net.IP `json:"static_ips,omitempty"`
|
||||
// Aliases contains a list of names which the dns server should resolve
|
||||
// to this container. Should only be set when DNSEnabled is true on the Network.
|
||||
// If aliases are set but there is no dns support for this network the
|
||||
// network interface implementation should ignore this and NOT error.
|
||||
// Optional.
|
||||
Aliases []string `json:"aliases,omitempty"`
|
||||
// StaticMac for this container. Optional.
|
||||
// swagger:strfmt string
|
||||
StaticMAC HardwareAddr `json:"static_mac,omitempty"`
|
||||
// InterfaceName for this container. Required in the backend.
|
||||
// Optional in the frontend. Will be filled with ethX (where X is a integer) when empty.
|
||||
InterfaceName string `json:"interface_name"`
|
||||
}
|
||||
|
||||
// NetworkOptions for a given container.
|
||||
type NetworkOptions struct {
|
||||
// ContainerID is the container id, used for iptables comments and ipam allocation.
|
||||
ContainerID string `json:"container_id"`
|
||||
// ContainerName is the container name, used as dns name.
|
||||
ContainerName string `json:"container_name"`
|
||||
// PortMappings contains the port mappings for this container
|
||||
PortMappings []PortMapping `json:"port_mappings,omitempty"`
|
||||
// Networks contains all networks with the PerNetworkOptions.
|
||||
// The map should contain at least one element.
|
||||
Networks map[string]PerNetworkOptions `json:"networks"`
|
||||
// List of custom DNS server for podman's DNS resolver.
|
||||
// Priority order will be kept as defined by user in the configuration.
|
||||
DNSServers []string `json:"dns_servers,omitempty"`
|
||||
}
|
||||
|
||||
// PortMapping is one or more ports that will be mapped into the container.
|
||||
type PortMapping struct {
|
||||
// HostIP is the IP that we will bind to on the host.
|
||||
// If unset, assumed to be 0.0.0.0 (all interfaces).
|
||||
HostIP string `json:"host_ip"`
|
||||
// ContainerPort is the port number that will be exposed from the
|
||||
// container.
|
||||
// Mandatory.
|
||||
ContainerPort uint16 `json:"container_port"`
|
||||
// HostPort is the port number that will be forwarded from the host into
|
||||
// the container.
|
||||
// If omitted, a random port on the host (guaranteed to be over 1024)
|
||||
// will be assigned.
|
||||
HostPort uint16 `json:"host_port"`
|
||||
// Range is the number of ports that will be forwarded, starting at
|
||||
// HostPort and ContainerPort and counting up.
|
||||
// This is 1-indexed, so 1 is assumed to be a single port (only the
|
||||
// Hostport:Containerport mapping will be added), 2 is two ports (both
|
||||
// Hostport:Containerport and Hostport+1:Containerport+1), etc.
|
||||
// If unset, assumed to be 1 (a single port).
|
||||
// Both hostport + range and containerport + range must be less than
|
||||
// 65536.
|
||||
Range uint16 `json:"range"`
|
||||
// Protocol is the protocol forward.
|
||||
// Must be either "tcp", "udp", and "sctp", or some combination of these
|
||||
// separated by commas.
|
||||
// If unset, assumed to be TCP.
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
// OCICNIPortMapping maps to the standard CNI portmapping Capability.
|
||||
// Deprecated: Do not use this struct for new fields. This only exists
|
||||
// for backwards compatibility.
|
||||
type OCICNIPortMapping struct {
|
||||
// HostPort is the port number on the host.
|
||||
HostPort int32 `json:"hostPort"`
|
||||
// ContainerPort is the port number inside the sandbox.
|
||||
ContainerPort int32 `json:"containerPort"`
|
||||
// Protocol is the protocol of the port mapping.
|
||||
Protocol string `json:"protocol"`
|
||||
// HostIP is the host ip to use.
|
||||
HostIP string `json:"hostIP"`
|
||||
}
|
||||
|
||||
type SetupOptions struct {
|
||||
NetworkOptions
|
||||
}
|
||||
|
||||
type TeardownOptions struct {
|
||||
NetworkOptions
|
||||
}
|
||||
|
||||
// FilterFunc can be passed to NetworkList to filter the networks.
|
||||
type FilterFunc func(Network) bool
|
||||
|
||||
type NetworkCreateOptions struct {
|
||||
// IgnoreIfExists if true, do not fail if the network already exists
|
||||
IgnoreIfExists bool
|
||||
}
|
4
vendor/github.com/containers/common/pkg/auth/auth.go
generated
vendored
4
vendor/github.com/containers/common/pkg/auth/auth.go
generated
vendored
@@ -10,7 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/pkg/util"
|
||||
passwd "github.com/containers/common/pkg/password"
|
||||
"github.com/containers/image/v5/docker"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/pkg/docker/config"
|
||||
@@ -269,7 +269,7 @@ func getUserAndPass(opts *LoginOptions, password, userFromAuthFile string) (user
|
||||
}
|
||||
if password == "" {
|
||||
fmt.Fprint(opts.Stdout, "Password: ")
|
||||
pass, err := util.ReadPassword(int(os.Stdin.Fd()))
|
||||
pass, err := passwd.Read(int(os.Stdin.Fd()))
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("reading password: %w", err)
|
||||
}
|
||||
|
57
vendor/github.com/containers/common/pkg/password/password_supported.go
generated
vendored
Normal file
57
vendor/github.com/containers/common/pkg/password/password_supported.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
//go:build linux || darwin || freebsd
|
||||
// +build linux darwin freebsd
|
||||
|
||||
package password
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
terminal "golang.org/x/term"
|
||||
)
|
||||
|
||||
var ErrInterrupt = errors.New("interrupted")
|
||||
|
||||
// Read reads a password from the terminal without echo.
|
||||
func Read(fd int) ([]byte, error) {
|
||||
// Store and restore the terminal status on interruptions to
|
||||
// avoid that the terminal remains in the password state
|
||||
// This is necessary as for https://github.com/golang/go/issues/31180
|
||||
|
||||
oldState, err := terminal.GetState(fd)
|
||||
if err != nil {
|
||||
return make([]byte, 0), err
|
||||
}
|
||||
|
||||
type Buffer struct {
|
||||
Buffer []byte
|
||||
Error error
|
||||
}
|
||||
errorChannel := make(chan Buffer, 1)
|
||||
|
||||
// SIGINT and SIGTERM restore the terminal, otherwise the no-echo mode would remain intact
|
||||
interruptChannel := make(chan os.Signal, 1)
|
||||
signal.Notify(interruptChannel, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer func() {
|
||||
signal.Stop(interruptChannel)
|
||||
close(interruptChannel)
|
||||
}()
|
||||
go func() {
|
||||
for range interruptChannel {
|
||||
if oldState != nil {
|
||||
_ = terminal.Restore(fd, oldState)
|
||||
}
|
||||
errorChannel <- Buffer{Buffer: make([]byte, 0), Error: ErrInterrupt}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
buf, err := terminal.ReadPassword(fd)
|
||||
errorChannel <- Buffer{Buffer: buf, Error: err}
|
||||
}()
|
||||
|
||||
buf := <-errorChannel
|
||||
return buf.Buffer, buf.Error
|
||||
}
|
@@ -1,21 +1,14 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package util
|
||||
package password
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
terminal "golang.org/x/term"
|
||||
)
|
||||
|
||||
// getRuntimeDir returns the runtime directory
|
||||
func GetRuntimeDir() (string, error) {
|
||||
return "", errors.New("this function is not implemented for windows")
|
||||
}
|
||||
|
||||
// ReadPassword reads a password from the terminal.
|
||||
func ReadPassword(fd int) ([]byte, error) {
|
||||
// Read reads a password from the terminal.
|
||||
func Read(fd int) ([]byte, error) {
|
||||
oldState, err := terminal.GetState(fd)
|
||||
if err != nil {
|
||||
return make([]byte, 0), err
|
57
vendor/github.com/containers/common/pkg/util/copy.go
generated
vendored
57
vendor/github.com/containers/common/pkg/util/copy.go
generated
vendored
@@ -1,57 +0,0 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ErrDetach indicates that an attach session was manually detached by
|
||||
// the user.
|
||||
var ErrDetach = errors.New("detached from container")
|
||||
|
||||
// CopyDetachable is similar to io.Copy but support a detach key sequence to break out.
|
||||
func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) {
|
||||
buf := make([]byte, 32*1024)
|
||||
for {
|
||||
nr, er := src.Read(buf)
|
||||
if nr > 0 {
|
||||
preservBuf := []byte{}
|
||||
for i, key := range keys {
|
||||
preservBuf = append(preservBuf, buf[0:nr]...)
|
||||
if nr != 1 || buf[0] != key {
|
||||
break
|
||||
}
|
||||
if i == len(keys)-1 {
|
||||
return 0, ErrDetach
|
||||
}
|
||||
nr, er = src.Read(buf)
|
||||
}
|
||||
var nw int
|
||||
var ew error
|
||||
if len(preservBuf) > 0 {
|
||||
nw, ew = dst.Write(preservBuf)
|
||||
nr = len(preservBuf)
|
||||
} else {
|
||||
nw, ew = dst.Write(buf[0:nr])
|
||||
}
|
||||
if nw > 0 {
|
||||
written += int64(nw)
|
||||
}
|
||||
if ew != nil {
|
||||
err = ew
|
||||
break
|
||||
}
|
||||
if nr != nw {
|
||||
err = io.ErrShortWrite
|
||||
break
|
||||
}
|
||||
}
|
||||
if er != nil {
|
||||
if er != io.EOF {
|
||||
err = er
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return written, err
|
||||
}
|
206
vendor/github.com/containers/common/pkg/util/util.go
generated
vendored
206
vendor/github.com/containers/common/pkg/util/util.go
generated
vendored
@@ -1,206 +0,0 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
UnknownPackage = "Unknown"
|
||||
)
|
||||
|
||||
var ErrInterrupt = errors.New("interrupted")
|
||||
|
||||
// Note: This function is copied from containers/podman libpod/util.go
|
||||
// Please see https://github.com/containers/common/pull/1460
|
||||
func queryPackageVersion(cmdArg ...string) string {
|
||||
output := UnknownPackage
|
||||
if 1 < len(cmdArg) {
|
||||
cmd := exec.Command(cmdArg[0], cmdArg[1:]...)
|
||||
if outp, err := cmd.Output(); err == nil {
|
||||
output = string(outp)
|
||||
deb := false
|
||||
if cmdArg[0] == "/usr/bin/dlocate" {
|
||||
// can return multiple matches
|
||||
l := strings.Split(output, "\n")
|
||||
output = l[0]
|
||||
deb = true
|
||||
} else if cmdArg[0] == "/usr/bin/dpkg" {
|
||||
deb = true
|
||||
}
|
||||
if deb {
|
||||
r := strings.Split(output, ": ")
|
||||
queryFormat := `${Package}_${Version}_${Architecture}`
|
||||
cmd = exec.Command("/usr/bin/dpkg-query", "-f", queryFormat, "-W", r[0])
|
||||
if outp, err := cmd.Output(); err == nil {
|
||||
output = string(outp)
|
||||
}
|
||||
}
|
||||
}
|
||||
if cmdArg[0] == "/sbin/apk" {
|
||||
prefix := cmdArg[len(cmdArg)-1] + " is owned by "
|
||||
output = strings.Replace(output, prefix, "", 1)
|
||||
}
|
||||
}
|
||||
return strings.Trim(output, "\n")
|
||||
}
|
||||
|
||||
// Note: This function is copied from containers/podman libpod/util.go
|
||||
// Please see https://github.com/containers/common/pull/1460
|
||||
func PackageVersion(program string) string { // program is full path
|
||||
_, err := os.Stat(program)
|
||||
if err != nil {
|
||||
return UnknownPackage
|
||||
}
|
||||
packagers := [][]string{
|
||||
{"/usr/bin/rpm", "-q", "-f"},
|
||||
{"/usr/bin/dlocate", "-F"}, // Debian, Ubuntu (quick)
|
||||
{"/usr/bin/dpkg", "-S"}, // Debian, Ubuntu (slow)
|
||||
{"/usr/bin/pacman", "-Qo"}, // Arch
|
||||
{"/usr/bin/qfile", "-qv"}, // Gentoo (quick)
|
||||
{"/usr/bin/equery", "b"}, // Gentoo (slow)
|
||||
{"/sbin/apk", "info", "-W"}, // Alpine
|
||||
{"/usr/local/sbin/pkg", "which", "-q"}, // FreeBSD
|
||||
}
|
||||
|
||||
for _, cmd := range packagers {
|
||||
cmd = append(cmd, program)
|
||||
if out := queryPackageVersion(cmd...); out != UnknownPackage {
|
||||
return out
|
||||
}
|
||||
}
|
||||
return UnknownPackage
|
||||
}
|
||||
|
||||
// Note: This function is copied from containers/podman libpod/util.go
|
||||
// Please see https://github.com/containers/common/pull/1460
|
||||
func ProgramVersion(program string) (string, error) {
|
||||
return programVersion(program, false)
|
||||
}
|
||||
|
||||
func ProgramVersionDnsname(program string) (string, error) {
|
||||
return programVersion(program, true)
|
||||
}
|
||||
|
||||
func programVersion(program string, dnsname bool) (string, error) {
|
||||
cmd := exec.Command(program, "--version")
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("`%v --version` failed: %v %v (%v)", program, stderr.String(), stdout.String(), err)
|
||||
}
|
||||
|
||||
output := strings.TrimSuffix(stdout.String(), "\n")
|
||||
// dnsname --version returns the information to stderr
|
||||
if dnsname {
|
||||
output = strings.TrimSuffix(stderr.String(), "\n")
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// StringInSlice determines if a string is in a string slice, returns bool
|
||||
func StringInSlice(s string, sl []string) bool {
|
||||
for _, i := range sl {
|
||||
if i == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// StringMatchRegexSlice determines if a given string matches one of the given regexes, returns bool
|
||||
func StringMatchRegexSlice(s string, re []string) bool {
|
||||
for _, r := range re {
|
||||
m, err := regexp.MatchString(r, s)
|
||||
if err == nil && m {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// FilterID is a function used to compare an id against a set of ids, if the
|
||||
// input is hex we check if the prefix matches. Otherwise we assume it is a
|
||||
// regex and try to match that.
|
||||
// see https://github.com/containers/podman/issues/18471 for why we do this
|
||||
func FilterID(id string, filters []string) bool {
|
||||
for _, want := range filters {
|
||||
isRegex := types.NotHexRegex.MatchString(want)
|
||||
if isRegex {
|
||||
match, err := regexp.MatchString(want, id)
|
||||
if err == nil && match {
|
||||
return true
|
||||
}
|
||||
} else if strings.HasPrefix(id, strings.ToLower(want)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// WaitForFile waits until a file has been created or the given timeout has occurred
|
||||
func WaitForFile(path string, chWait chan error, timeout time.Duration) (bool, error) {
|
||||
var inotifyEvents chan fsnotify.Event
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err == nil {
|
||||
if err := watcher.Add(filepath.Dir(path)); err == nil {
|
||||
inotifyEvents = watcher.Events
|
||||
}
|
||||
defer func() {
|
||||
if err := watcher.Close(); err != nil {
|
||||
logrus.Errorf("Failed to close fsnotify watcher: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
var timeoutChan <-chan time.Time
|
||||
|
||||
if timeout != 0 {
|
||||
timeoutChan = time.After(timeout)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case e := <-chWait:
|
||||
return true, e
|
||||
case <-inotifyEvents:
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return false, nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return false, err
|
||||
}
|
||||
case <-time.After(25 * time.Millisecond):
|
||||
// Check periodically for the file existence. It is needed
|
||||
// if the inotify watcher could not have been created. It is
|
||||
// also useful when using inotify as if for any reasons we missed
|
||||
// a notification, we won't hang the process.
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return false, nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return false, err
|
||||
}
|
||||
case <-timeoutChan:
|
||||
return false, fmt.Errorf("timed out waiting for file %s", path)
|
||||
}
|
||||
}
|
||||
}
|
135
vendor/github.com/containers/common/pkg/util/util_supported.go
generated
vendored
135
vendor/github.com/containers/common/pkg/util/util_supported.go
generated
vendored
@@ -1,135 +0,0 @@
|
||||
//go:build linux || darwin || freebsd
|
||||
// +build linux darwin freebsd
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/storage/pkg/homedir"
|
||||
"github.com/containers/storage/pkg/unshare"
|
||||
"github.com/sirupsen/logrus"
|
||||
terminal "golang.org/x/term"
|
||||
)
|
||||
|
||||
var (
|
||||
rootlessRuntimeDirOnce sync.Once
|
||||
rootlessRuntimeDir string
|
||||
)
|
||||
|
||||
// isWriteableOnlyByOwner checks that the specified permission mask allows write
|
||||
// access only to the owner.
|
||||
func isWriteableOnlyByOwner(perm os.FileMode) bool {
|
||||
return (perm & 0o722) == 0o700
|
||||
}
|
||||
|
||||
// GetRuntimeDir returns the runtime directory
|
||||
func GetRuntimeDir() (string, error) {
|
||||
var rootlessRuntimeDirError error
|
||||
|
||||
rootlessRuntimeDirOnce.Do(func() {
|
||||
runtimeDir, err := homedir.GetRuntimeDir()
|
||||
if err != nil {
|
||||
logrus.Debug(err)
|
||||
}
|
||||
if runtimeDir != "" {
|
||||
st, err := os.Stat(runtimeDir)
|
||||
if err != nil {
|
||||
rootlessRuntimeDirError = err
|
||||
return
|
||||
}
|
||||
if int(st.Sys().(*syscall.Stat_t).Uid) != os.Geteuid() {
|
||||
rootlessRuntimeDirError = fmt.Errorf("XDG_RUNTIME_DIR directory %q is not owned by the current user", runtimeDir)
|
||||
return
|
||||
}
|
||||
}
|
||||
uid := fmt.Sprintf("%d", unshare.GetRootlessUID())
|
||||
if runtimeDir == "" {
|
||||
tmpDir := filepath.Join("/run", "user", uid)
|
||||
if err := os.MkdirAll(tmpDir, 0o700); err != nil {
|
||||
logrus.Debugf("unable to make temp dir: %v", err)
|
||||
}
|
||||
st, err := os.Stat(tmpDir)
|
||||
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && isWriteableOnlyByOwner(st.Mode().Perm()) {
|
||||
runtimeDir = tmpDir
|
||||
}
|
||||
}
|
||||
if runtimeDir == "" {
|
||||
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("podman-run-%s", uid))
|
||||
if err := os.MkdirAll(tmpDir, 0o700); err != nil {
|
||||
logrus.Debugf("unable to make temp dir %v", err)
|
||||
}
|
||||
st, err := os.Stat(tmpDir)
|
||||
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && isWriteableOnlyByOwner(st.Mode().Perm()) {
|
||||
runtimeDir = tmpDir
|
||||
}
|
||||
}
|
||||
if runtimeDir == "" {
|
||||
home := os.Getenv("HOME")
|
||||
if home == "" {
|
||||
rootlessRuntimeDirError = errors.New("neither XDG_RUNTIME_DIR nor HOME was set non-empty")
|
||||
return
|
||||
}
|
||||
resolvedHome, err := filepath.EvalSymlinks(home)
|
||||
if err != nil {
|
||||
rootlessRuntimeDirError = fmt.Errorf("cannot resolve home: %w", err)
|
||||
return
|
||||
}
|
||||
runtimeDir = filepath.Join(resolvedHome, "rundir")
|
||||
}
|
||||
rootlessRuntimeDir = runtimeDir
|
||||
})
|
||||
|
||||
if rootlessRuntimeDirError != nil {
|
||||
return "", rootlessRuntimeDirError
|
||||
}
|
||||
return rootlessRuntimeDir, nil
|
||||
}
|
||||
|
||||
// ReadPassword reads a password from the terminal without echo.
|
||||
func ReadPassword(fd int) ([]byte, error) {
|
||||
// Store and restore the terminal status on interruptions to
|
||||
// avoid that the terminal remains in the password state
|
||||
// This is necessary as for https://github.com/golang/go/issues/31180
|
||||
|
||||
oldState, err := terminal.GetState(fd)
|
||||
if err != nil {
|
||||
return make([]byte, 0), err
|
||||
}
|
||||
|
||||
type Buffer struct {
|
||||
Buffer []byte
|
||||
Error error
|
||||
}
|
||||
errorChannel := make(chan Buffer, 1)
|
||||
|
||||
// SIGINT and SIGTERM restore the terminal, otherwise the no-echo mode would remain intact
|
||||
interruptChannel := make(chan os.Signal, 1)
|
||||
signal.Notify(interruptChannel, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer func() {
|
||||
signal.Stop(interruptChannel)
|
||||
close(interruptChannel)
|
||||
}()
|
||||
go func() {
|
||||
for range interruptChannel {
|
||||
if oldState != nil {
|
||||
_ = terminal.Restore(fd, oldState)
|
||||
}
|
||||
errorChannel <- Buffer{Buffer: make([]byte, 0), Error: ErrInterrupt}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
buf, err := terminal.ReadPassword(fd)
|
||||
errorChannel <- Buffer{Buffer: buf, Error: err}
|
||||
}()
|
||||
|
||||
buf := <-errorChannel
|
||||
return buf.Buffer, buf.Error
|
||||
}
|
Reference in New Issue
Block a user