mirror of
https://github.com/containers/podman.git
synced 2025-07-18 01:57:24 +08:00
add --module flag
Support a new concept in containers.conf called "modules". A "module" is a containers.conf file located at a specific directory. More than one module can be loaded in the specified order, following existing override semantics. There are three directories to load modules from: - $CONFIG_HOME/containers/containers.conf.modules - /etc/containers/containers.conf.modules - /usr/share/containers/containers.conf.modules With CONFIG_HOME pointing to $HOME/.config or, if set, $XDG_CONFIG_HOME. Absolute paths will be loaded as is, relative paths will be resolved relative to the three directories above allowing for admin configs (/etc/) to override system configs (/usr/share/) and user configs ($CONFIG_HOME) to override admin configs. Pulls in containers/common/pull/1599. Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -1540,6 +1541,38 @@ func AutocompleteCgroupManager(cmd *cobra.Command, args []string, toComplete str
|
|||||||
return types, cobra.ShellCompDirectiveNoFileComp
|
return types, cobra.ShellCompDirectiveNoFileComp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AutocompleteContainersConfModules- Autocomplete containers.conf modules.
|
||||||
|
func AutocompleteContainersConfModules(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
dirs, err := config.ModuleDirectories()
|
||||||
|
if err != nil {
|
||||||
|
return nil, cobra.ShellCompDirectiveDefault
|
||||||
|
}
|
||||||
|
var modules []string
|
||||||
|
for _, d := range dirs {
|
||||||
|
cleanedD := filepath.Clean(d)
|
||||||
|
moduleD := cleanedD + string(os.PathSeparator)
|
||||||
|
_ = filepath.Walk(d,
|
||||||
|
func(path string, f os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
moduleName := strings.TrimPrefix(path, moduleD)
|
||||||
|
|
||||||
|
if toComplete != "" && !strings.HasPrefix(moduleName, toComplete) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if filepath.Clean(path) == cleanedD || f.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
modules = append(modules, moduleName)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return modules, cobra.ShellCompDirectiveDefault
|
||||||
|
}
|
||||||
|
|
||||||
// AutocompleteEventBackend - Autocomplete event backend options.
|
// AutocompleteEventBackend - Autocomplete event backend options.
|
||||||
// -> "file", "journald", "none"
|
// -> "file", "journald", "none"
|
||||||
func AutocompleteEventBackend(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
func AutocompleteEventBackend(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
@ -11,6 +11,8 @@ import (
|
|||||||
"github.com/containers/podman/v4/pkg/domain/entities"
|
"github.com/containers/podman/v4/pkg/domain/entities"
|
||||||
"github.com/containers/podman/v4/pkg/rootless"
|
"github.com/containers/podman/v4/pkg/rootless"
|
||||||
"github.com/containers/podman/v4/pkg/util"
|
"github.com/containers/podman/v4/pkg/util"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -39,19 +41,58 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// PodmanConfig returns an entities.PodmanConfig built up from
|
// PodmanConfig returns an entities.PodmanConfig built up from
|
||||||
// environment and CLI
|
// environment and CLI.
|
||||||
func PodmanConfig() *entities.PodmanConfig {
|
func PodmanConfig() *entities.PodmanConfig {
|
||||||
podmanSync.Do(newPodmanConfig)
|
podmanSync.Do(newPodmanConfig)
|
||||||
return &podmanOptions
|
return &podmanOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the index of os.Args where to start parsing CLI flags.
|
||||||
|
// An index > 1 implies Podman is running in shell completion.
|
||||||
|
func parseIndex() int {
|
||||||
|
// The shell completion logic will call a command called "__complete" or "__completeNoDesc"
|
||||||
|
// This command will always be the second argument
|
||||||
|
// To still parse --remote correctly in this case we have to set args offset to two in this case
|
||||||
|
if len(os.Args) > 1 && (os.Args[1] == cobra.ShellCompRequestCmd || os.Args[1] == cobra.ShellCompNoDescRequestCmd) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the containers.conf modules to load.
|
||||||
|
func containersConfModules() ([]string, error) {
|
||||||
|
index := parseIndex()
|
||||||
|
if index > 1 {
|
||||||
|
// Do not load the modules during shell completion.
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var modules []string
|
||||||
|
fs := pflag.NewFlagSet("module", pflag.ContinueOnError)
|
||||||
|
fs.ParseErrorsWhitelist.UnknownFlags = true
|
||||||
|
fs.Usage = func() {}
|
||||||
|
fs.SetInterspersed(false)
|
||||||
|
fs.StringSliceVar(&modules, "module", nil, "")
|
||||||
|
fs.BoolP("help", "h", false, "") // Need a fake help flag to avoid the `pflag: help requested` error
|
||||||
|
return modules, fs.Parse(os.Args[index:])
|
||||||
|
}
|
||||||
|
|
||||||
func newPodmanConfig() {
|
func newPodmanConfig() {
|
||||||
|
modules, err := containersConfModules()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
if err := setXdgDirs(); err != nil {
|
if err := setXdgDirs(); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err.Error())
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig, err := config.Default()
|
defaultConfig, err := config.New(&config.Options{
|
||||||
|
SetDefault: true, // This makes sure that following calls to config.Default() return this config
|
||||||
|
Modules: modules,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprint(os.Stderr, "Failed to obtain podman configuration: "+err.Error())
|
fmt.Fprint(os.Stderr, "Failed to obtain podman configuration: "+err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containers/podman/v4/pkg/domain/entities"
|
"github.com/containers/podman/v4/pkg/domain/entities"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,14 +49,7 @@ func IsRemote() bool {
|
|||||||
urlFlagName := "url"
|
urlFlagName := "url"
|
||||||
fs.String(urlFlagName, "", "")
|
fs.String(urlFlagName, "", "")
|
||||||
|
|
||||||
// The shell completion logic will call a command called "__complete" or "__completeNoDesc"
|
_ = fs.Parse(os.Args[parseIndex():])
|
||||||
// This command will always be the second argument
|
|
||||||
// To still parse --remote correctly in this case we have to set args offset to two in this case
|
|
||||||
start := 1
|
|
||||||
if len(os.Args) > 1 && (os.Args[1] == cobra.ShellCompRequestCmd || os.Args[1] == cobra.ShellCompNoDescRequestCmd) {
|
|
||||||
start = 2
|
|
||||||
}
|
|
||||||
_ = fs.Parse(os.Args[start:])
|
|
||||||
// --connection or --url implies --remote
|
// --connection or --url implies --remote
|
||||||
remoteFromCLI.Value = remoteFromCLI.Value || fs.Changed(connectionFlagName) || fs.Changed(urlFlagName) || fs.Changed(hostFlagName) || fs.Changed(contextFlagName)
|
remoteFromCLI.Value = remoteFromCLI.Value || fs.Changed(connectionFlagName) || fs.Changed(urlFlagName) || fs.Changed(hostFlagName) || fs.Changed(contextFlagName)
|
||||||
})
|
})
|
||||||
|
@ -451,6 +451,14 @@ func rootFlags(cmd *cobra.Command, podmanConfig *entities.PodmanConfig) {
|
|||||||
}
|
}
|
||||||
podmanConfig.Remote = true
|
podmanConfig.Remote = true
|
||||||
} else {
|
} else {
|
||||||
|
// The --module's are actually used and parsed in
|
||||||
|
// `registry.PodmanConfig()`. But we also need to expose them
|
||||||
|
// as a flag here to a) make sure that rootflags are aware of
|
||||||
|
// this flag and b) to have shell completions.
|
||||||
|
moduleFlagName := "module"
|
||||||
|
pFlags.StringSlice(moduleFlagName, nil, "Load the containers.conf(5) module")
|
||||||
|
_ = cmd.RegisterFlagCompletionFunc(moduleFlagName, common.AutocompleteContainersConfModules)
|
||||||
|
|
||||||
// A *hidden* flag to change the database backend.
|
// A *hidden* flag to change the database backend.
|
||||||
pFlags.StringVar(&podmanConfig.ContainersConf.Engine.DBBackend, "db-backend", podmanConfig.ContainersConfDefaultsRO.Engine.DBBackend, "Database backend to use")
|
pFlags.StringVar(&podmanConfig.ContainersConf.Engine.DBBackend, "db-backend", podmanConfig.ContainersConfDefaultsRO.Engine.DBBackend, "Database backend to use")
|
||||||
|
|
||||||
|
@ -88,6 +88,12 @@ This will override *imagestore* option in `containers-storage.conf(5)`, refer to
|
|||||||
|
|
||||||
Log messages at and above specified level: __debug__, __info__, __warn__, __error__, __fatal__ or __panic__ (default: _warn_)
|
Log messages at and above specified level: __debug__, __info__, __warn__, __error__, __fatal__ or __panic__ (default: _warn_)
|
||||||
|
|
||||||
|
#### **--module**=*path*
|
||||||
|
|
||||||
|
Load the specified `containers.conf(5)` module. Can be an absolute or relative path. Please refer to `containers.conf(5)` for details.
|
||||||
|
|
||||||
|
This feature is not supported on the remote client, including Mac and Windows (excluding WSL2) machines
|
||||||
|
|
||||||
#### **--network-cmd-path**=*path*
|
#### **--network-cmd-path**=*path*
|
||||||
Path to the `slirp4netns(1)` command binary to use for setting up a slirp4netns network.
|
Path to the `slirp4netns(1)` command binary to use for setting up a slirp4netns network.
|
||||||
If "" is used, then the binary will first be searched using the `helper_binaries_dir` option in `containers.conf`, and second using the `$PATH` environment variable.
|
If "" is used, then the binary will first be searched using the `helper_binaries_dir` option in `containers.conf`, and second using the `$PATH` environment variable.
|
||||||
|
4
go.mod
4
go.mod
@ -13,7 +13,7 @@ require (
|
|||||||
github.com/containernetworking/cni v1.1.2
|
github.com/containernetworking/cni v1.1.2
|
||||||
github.com/containernetworking/plugins v1.3.0
|
github.com/containernetworking/plugins v1.3.0
|
||||||
github.com/containers/buildah v1.31.1-0.20230722114901-5ece066f82c6
|
github.com/containers/buildah v1.31.1-0.20230722114901-5ece066f82c6
|
||||||
github.com/containers/common v0.55.1-0.20230811093040-524b4d5c12f9
|
github.com/containers/common v0.55.1-0.20230814161508-b70b0c49600e
|
||||||
github.com/containers/conmon v2.0.20+incompatible
|
github.com/containers/conmon v2.0.20+incompatible
|
||||||
github.com/containers/image/v5 v5.26.1-0.20230807184415-3fb422379cfa
|
github.com/containers/image/v5 v5.26.1-0.20230807184415-3fb422379cfa
|
||||||
github.com/containers/libhvee v0.4.0
|
github.com/containers/libhvee v0.4.0
|
||||||
@ -157,7 +157,7 @@ require (
|
|||||||
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
|
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pkg/sftp v1.13.5 // indirect
|
github.com/pkg/sftp v1.13.6 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/proglottis/gpgme v0.1.3 // indirect
|
github.com/proglottis/gpgme v0.1.3 // indirect
|
||||||
github.com/rivo/uniseg v0.4.4 // indirect
|
github.com/rivo/uniseg v0.4.4 // indirect
|
||||||
|
22
go.sum
22
go.sum
@ -246,8 +246,8 @@ github.com/containernetworking/plugins v1.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q
|
|||||||
github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0=
|
github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0=
|
||||||
github.com/containers/buildah v1.31.1-0.20230722114901-5ece066f82c6 h1:K/S8SFQsnnNTF0Ws58SrBD9L0EuClzAG8Zp08d7+6AA=
|
github.com/containers/buildah v1.31.1-0.20230722114901-5ece066f82c6 h1:K/S8SFQsnnNTF0Ws58SrBD9L0EuClzAG8Zp08d7+6AA=
|
||||||
github.com/containers/buildah v1.31.1-0.20230722114901-5ece066f82c6/go.mod h1:0sptTFBBtSznLqoTh80DfvMOCNbdRsNRgVOKhBhrupA=
|
github.com/containers/buildah v1.31.1-0.20230722114901-5ece066f82c6/go.mod h1:0sptTFBBtSznLqoTh80DfvMOCNbdRsNRgVOKhBhrupA=
|
||||||
github.com/containers/common v0.55.1-0.20230811093040-524b4d5c12f9 h1:TJIOB2FmgB0YpBby30WmnocbvfCeiJkRORFZjyrkso8=
|
github.com/containers/common v0.55.1-0.20230814161508-b70b0c49600e h1:MD15BW3p8JtzyKx5fLHOQsPyPXZslYth15cu90ttB2o=
|
||||||
github.com/containers/common v0.55.1-0.20230811093040-524b4d5c12f9/go.mod h1:P80FfWkQ7oITVaBAHF50gZVzsj198bJ2IyQjHVsdBVk=
|
github.com/containers/common v0.55.1-0.20230814161508-b70b0c49600e/go.mod h1:u6f5WyhJnfwoKdYlqK8b33OJ2DyYtXJ56jz1K4G7ynw=
|
||||||
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
|
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
|
||||||
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
||||||
github.com/containers/image/v5 v5.26.1-0.20230807184415-3fb422379cfa h1:wDfVQtc6ik2MvsUmu/YRSyBAE5YUxdjcEDtuT1q2KDo=
|
github.com/containers/image/v5 v5.26.1-0.20230807184415-3fb422379cfa h1:wDfVQtc6ik2MvsUmu/YRSyBAE5YUxdjcEDtuT1q2KDo=
|
||||||
@ -846,8 +846,8 @@ github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV
|
|||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go=
|
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||||
github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
|
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||||
@ -1046,6 +1046,7 @@ github.com/ysmood/leakless v0.8.0 h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak
|
|||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||||
@ -1102,8 +1103,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@ -1139,6 +1141,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
|||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -1184,6 +1187,8 @@ golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1
|
|||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@ -1205,6 +1210,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -1288,13 +1294,17 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
||||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -1306,6 +1316,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
||||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@ -1364,6 +1375,7 @@ golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4X
|
|||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
||||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
@ -33,7 +33,7 @@ func ExecuteTransfer(src, dst string, parentFlags []string, quiet bool, sshMode
|
|||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
confR, err := config.NewConfig("") // create a hand made config for the remote engine since we might use remote and native at once
|
confR, err := config.New(nil) // create a hand made config for the remote engine since we might use remote and native at once
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, fmt.Errorf("could not make config: %w", err)
|
return nil, nil, nil, nil, fmt.Errorf("could not make config: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -304,6 +304,13 @@ func CreateExitCommandArgs(storageConfig storageTypes.StoreOptions, config *conf
|
|||||||
if syslog {
|
if syslog {
|
||||||
command = append(command, "--syslog")
|
command = append(command, "--syslog")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure that loaded containers.conf modules are passed down to the
|
||||||
|
// callback as well.
|
||||||
|
for _, module := range config.LoadedModules() {
|
||||||
|
command = append(command, "--module", module)
|
||||||
|
}
|
||||||
|
|
||||||
command = append(command, []string{"container", "cleanup"}...)
|
command = append(command, []string{"container", "cleanup"}...)
|
||||||
|
|
||||||
if rm {
|
if rm {
|
||||||
|
@ -83,4 +83,98 @@ EOF
|
|||||||
is "$output" "Error:.*no such container"
|
is "$output" "Error:.*no such container"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "podman --module - absolute path" {
|
||||||
|
skip_if_remote "--module is not supported for remote clients"
|
||||||
|
|
||||||
|
random_data="expected_annotation_$(random_string 15)"
|
||||||
|
conf_tmp="$PODMAN_TMPDIR/test.conf"
|
||||||
|
cat > $conf_tmp <<EOF
|
||||||
|
[containers]
|
||||||
|
annotations=['module=$random_data']
|
||||||
|
EOF
|
||||||
|
|
||||||
|
run_podman --module=$conf_tmp create -q $IMAGE
|
||||||
|
cid="$output"
|
||||||
|
run_podman container inspect $cid --format '{{index .Config.Annotations "module"}}'
|
||||||
|
is "$output" "$random_data" "container annotation should include the one from the --module"
|
||||||
|
|
||||||
|
run_podman rm -f $cid
|
||||||
|
|
||||||
|
# Nonexistent module path
|
||||||
|
nonesuch=${PODMAN_TMPDIR}/nonexistent
|
||||||
|
run_podman 1 --module=$nonesuch sdfsdfdsf
|
||||||
|
is "$output" "Failed to obtain podman configuration: could not resolve module \"$nonesuch\": stat $nonesuch: no such file or directory" \
|
||||||
|
"--module=ENOENT"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "podman --module - XDG_CONFIG_HOME" {
|
||||||
|
skip_if_remote "--module is not supported for remote clients"
|
||||||
|
skip_if_not_rootless "loading a module from XDG_CONFIG_HOME requires rootless"
|
||||||
|
|
||||||
|
fake_home="$PODMAN_TMPDIR/home/.config"
|
||||||
|
fake_modules_dir="$fake_home/containers/containers.conf.modules"
|
||||||
|
mkdir -p $fake_modules_dir
|
||||||
|
|
||||||
|
random_data="expected_annotation_$(random_string 15)"
|
||||||
|
module_name="test.conf"
|
||||||
|
conf_tmp="$fake_modules_dir/$module_name"
|
||||||
|
cat > $conf_tmp <<EOF
|
||||||
|
[containers]
|
||||||
|
annotations=['module=$random_data']
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Test loading a relative path (test.conf) as a module. This should find
|
||||||
|
# the one in the fake XDG_CONFIG_HOME. We cannot override /etc or
|
||||||
|
# /usr/share in the tests here, so for those paths we need to rely on the
|
||||||
|
# unit tests in containers/common/pkg/config and manual QE.
|
||||||
|
XDG_CONFIG_HOME=$fake_home run_podman --module $module_name run -d -q $IMAGE sleep infinity
|
||||||
|
cid="$output"
|
||||||
|
run_podman container inspect $cid --format '{{index .Config.Annotations "module"}}'
|
||||||
|
is "$output" "$random_data" "container annotation should include the one from the --module"
|
||||||
|
|
||||||
|
# Now make sure that conmon's exit-command points to the _absolute path_ of
|
||||||
|
# the module.
|
||||||
|
run_podman container inspect $cid --format "{{ .State.ConmonPid }}"
|
||||||
|
conmon_pid="$output"
|
||||||
|
is "$(< /proc/$conmon_pid/cmdline)" ".*--exit-command-arg--module--exit-command-arg$conf_tmp.*" "conmon's exit-command uses the module"
|
||||||
|
run_podman rm -f -t0 $cid
|
||||||
|
|
||||||
|
# Corrupt module file
|
||||||
|
cat > $conf_tmp <<EOF
|
||||||
|
[containers]
|
||||||
|
sdf=
|
||||||
|
EOF
|
||||||
|
XDG_CONFIG_HOME=$fake_home run_podman 1 --module $module_name
|
||||||
|
is "$output" "Failed to obtain podman configuration: reading additional config \"$conf_tmp\": decode configuration $conf_tmp: toml: line 3 (last key \"containers.sdf\"): expected value but found '\n' instead" \
|
||||||
|
"Corrupt module file"
|
||||||
|
|
||||||
|
# Nonexistent module name
|
||||||
|
nonesuch=assume-this-does-not-exist-$(random_string)
|
||||||
|
XDG_CONFIG_HOME=$fake_home run_podman 1 --module=$nonesuch invalid-command
|
||||||
|
expect="Failed to obtain podman configuration: could not resolve module \"$nonesuch\": 3 errors occurred:"
|
||||||
|
for dir in $fake_home /etc /usr/share;do
|
||||||
|
expect+=$'\n\t'"* stat $dir/containers/containers.conf.modules/$nonesuch: no such file or directory"
|
||||||
|
done
|
||||||
|
is "$output" "$expect" "--module=ENOENT : error message"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Too hard to test in 600-completion.bats because of the remote/rootless check
|
||||||
|
@test "podman --module - command-line completion" {
|
||||||
|
skip_if_remote "--module is not supported for remote clients"
|
||||||
|
skip_if_not_rootless "loading a module from XDG_CONFIG_HOME requires rootless"
|
||||||
|
|
||||||
|
fake_home="$PODMAN_TMPDIR/home/.config"
|
||||||
|
fake_modules_dir="$fake_home/containers/containers.conf.modules"
|
||||||
|
mkdir -p $fake_modules_dir
|
||||||
|
|
||||||
|
m1=m1odule_$(random_string)
|
||||||
|
m2=m2$(random_string)
|
||||||
|
|
||||||
|
touch $fake_modules_dir/{$m2,$m1}
|
||||||
|
XDG_CONFIG_HOME=$fake_home run_podman __completeNoDesc --module ""
|
||||||
|
# Even if there are modules in /etc or elsewhere, these will be first
|
||||||
|
assert "${lines[0]}" = "$m1" "completion finds module 1"
|
||||||
|
assert "${lines[1]}" = "$m2" "completion finds module 2"
|
||||||
|
}
|
||||||
|
|
||||||
# vim: filetype=sh
|
# vim: filetype=sh
|
||||||
|
200
vendor/github.com/containers/common/pkg/config/config.go
generated
vendored
200
vendor/github.com/containers/common/pkg/config/config.go
generated
vendored
@ -3,14 +3,11 @@ package config
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/containers/common/libnetwork/types"
|
"github.com/containers/common/libnetwork/types"
|
||||||
@ -81,6 +78,8 @@ type Config struct {
|
|||||||
ConfigMaps ConfigMapConfig `toml:"configmaps"`
|
ConfigMaps ConfigMapConfig `toml:"configmaps"`
|
||||||
// Farms defines configurations for the buildfarm farms
|
// Farms defines configurations for the buildfarm farms
|
||||||
Farms FarmConfig `toml:"farms"`
|
Farms FarmConfig `toml:"farms"`
|
||||||
|
|
||||||
|
loadedModules []string // only used at runtime to store which modules were loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainersConfig represents the "containers" TOML config table
|
// ContainersConfig represents the "containers" TOML config table
|
||||||
@ -708,166 +707,6 @@ func (c *EngineConfig) ImagePlatformToRuntime(os string, arch string) string {
|
|||||||
return c.OCIRuntime
|
return c.OCIRuntime
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig creates a new Config. It starts with an empty config and, if
|
|
||||||
// specified, merges the config at `userConfigPath` path. Depending if we're
|
|
||||||
// running as root or rootless, we then merge the system configuration followed
|
|
||||||
// by merging the default config (hard-coded default in memory).
|
|
||||||
// Note that the OCI runtime is hard-set to `crun` if we're running on a system
|
|
||||||
// with cgroupv2v2. Other OCI runtimes are not yet supporting cgroupv2v2. This
|
|
||||||
// might change in the future.
|
|
||||||
func NewConfig(userConfigPath string) (*Config, error) {
|
|
||||||
// Generate the default config for the system
|
|
||||||
config, err := DefaultConfig()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, gather the system configs and merge them as needed.
|
|
||||||
configs, err := systemConfigs()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("finding config on system: %w", err)
|
|
||||||
}
|
|
||||||
for _, path := range configs {
|
|
||||||
// Merge changes in later configs with the previous configs.
|
|
||||||
// Each config file that specified fields, will override the
|
|
||||||
// previous fields.
|
|
||||||
if err = readConfigFromFile(path, config); err != nil {
|
|
||||||
return nil, fmt.Errorf("reading system config %q: %w", path, err)
|
|
||||||
}
|
|
||||||
logrus.Debugf("Merged system config %q", path)
|
|
||||||
logrus.Tracef("%+v", config)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the caller specified a config path to use, then we read it to
|
|
||||||
// override the system defaults.
|
|
||||||
if userConfigPath != "" {
|
|
||||||
var err error
|
|
||||||
// readConfigFromFile reads in container config in the specified
|
|
||||||
// file and then merge changes with the current default.
|
|
||||||
if err = readConfigFromFile(userConfigPath, config); err != nil {
|
|
||||||
return nil, fmt.Errorf("reading user config %q: %w", userConfigPath, err)
|
|
||||||
}
|
|
||||||
logrus.Debugf("Merged user config %q", userConfigPath)
|
|
||||||
logrus.Tracef("%+v", config)
|
|
||||||
}
|
|
||||||
config.addCAPPrefix()
|
|
||||||
|
|
||||||
if err := config.Validate(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := config.setupEnv(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// readConfigFromFile reads the specified config file at `path` and attempts to
|
|
||||||
// unmarshal its content into a Config. The config param specifies the previous
|
|
||||||
// default config. If the path, only specifies a few fields in the Toml file
|
|
||||||
// the defaults from the config parameter will be used for all other fields.
|
|
||||||
func readConfigFromFile(path string, config *Config) error {
|
|
||||||
logrus.Tracef("Reading configuration file %q", path)
|
|
||||||
meta, err := toml.DecodeFile(path, config)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("decode configuration %v: %w", path, err)
|
|
||||||
}
|
|
||||||
keys := meta.Undecoded()
|
|
||||||
if len(keys) > 0 {
|
|
||||||
logrus.Debugf("Failed to decode the keys %q from %q.", keys, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// addConfigs will search one level in the config dirPath for config files
|
|
||||||
// If the dirPath does not exist, addConfigs will return nil
|
|
||||||
func addConfigs(dirPath string, configs []string) ([]string, error) {
|
|
||||||
newConfigs := []string{}
|
|
||||||
|
|
||||||
err := filepath.WalkDir(dirPath,
|
|
||||||
// WalkFunc to read additional configs
|
|
||||||
func(path string, d fs.DirEntry, err error) error {
|
|
||||||
switch {
|
|
||||||
case err != nil:
|
|
||||||
// return error (could be a permission problem)
|
|
||||||
return err
|
|
||||||
case d.IsDir():
|
|
||||||
if path != dirPath {
|
|
||||||
// make sure to not recurse into sub-directories
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
// ignore directories
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
// only add *.conf files
|
|
||||||
if strings.HasSuffix(path, ".conf") {
|
|
||||||
newConfigs = append(newConfigs, path)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
sort.Strings(newConfigs)
|
|
||||||
return append(configs, newConfigs...), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the list of configuration files, if they exist in order of hierarchy.
|
|
||||||
// The files are read in order and each new file can/will override previous
|
|
||||||
// file settings.
|
|
||||||
func systemConfigs() (configs []string, finalErr error) {
|
|
||||||
if path := os.Getenv("CONTAINERS_CONF_OVERRIDE"); path != "" {
|
|
||||||
if _, err := os.Stat(path); err != nil {
|
|
||||||
return nil, fmt.Errorf("CONTAINERS_CONF_OVERRIDE file: %w", err)
|
|
||||||
}
|
|
||||||
// Add the override config last to make sure it can override any
|
|
||||||
// previous settings.
|
|
||||||
defer func() {
|
|
||||||
if finalErr == nil {
|
|
||||||
configs = append(configs, path)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if path := os.Getenv("CONTAINERS_CONF"); path != "" {
|
|
||||||
if _, err := os.Stat(path); err != nil {
|
|
||||||
return nil, fmt.Errorf("CONTAINERS_CONF file: %w", err)
|
|
||||||
}
|
|
||||||
return append(configs, path), nil
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(DefaultContainersConfig); err == nil {
|
|
||||||
configs = append(configs, DefaultContainersConfig)
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(OverrideContainersConfig); err == nil {
|
|
||||||
configs = append(configs, OverrideContainersConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
configs, err = addConfigs(OverrideContainersConfig+".d", configs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
path, err := ifRootlessConfigPath()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if path != "" {
|
|
||||||
if _, err := os.Stat(path); err == nil {
|
|
||||||
configs = append(configs, path)
|
|
||||||
}
|
|
||||||
configs, err = addConfigs(path+".d", configs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return configs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckCgroupsAndAdjustConfig checks if we're running rootless with the systemd
|
// CheckCgroupsAndAdjustConfig checks if we're running rootless with the systemd
|
||||||
// cgroup manager. In case the user session isn't available, we're switching the
|
// cgroup manager. In case the user session isn't available, we're switching the
|
||||||
// cgroup manager to cgroupfs. Note, this only applies to rootless.
|
// cgroup manager to cgroupfs. Note, this only applies to rootless.
|
||||||
@ -1190,37 +1029,6 @@ func rootlessConfigPath() (string, error) {
|
|||||||
return filepath.Join(home, UserOverrideContainersConfig), nil
|
return filepath.Join(home, UserOverrideContainersConfig), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
configErr error
|
|
||||||
configMutex sync.Mutex
|
|
||||||
config *Config
|
|
||||||
)
|
|
||||||
|
|
||||||
// Default returns the default container config.
|
|
||||||
// Configuration files will be read in the following files:
|
|
||||||
// * /usr/share/containers/containers.conf
|
|
||||||
// * /etc/containers/containers.conf
|
|
||||||
// * $HOME/.config/containers/containers.conf # When run in rootless mode
|
|
||||||
// Fields in latter files override defaults set in previous files and the
|
|
||||||
// default config.
|
|
||||||
// None of these files are required, and not all fields need to be specified
|
|
||||||
// in each file, only the fields you want to override.
|
|
||||||
// The system defaults container config files can be overwritten using the
|
|
||||||
// CONTAINERS_CONF environment variable. This is usually done for testing.
|
|
||||||
func Default() (*Config, error) {
|
|
||||||
configMutex.Lock()
|
|
||||||
defer configMutex.Unlock()
|
|
||||||
if config != nil || configErr != nil {
|
|
||||||
return config, configErr
|
|
||||||
}
|
|
||||||
return defConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
func defConfig() (*Config, error) {
|
|
||||||
config, configErr = NewConfig("")
|
|
||||||
return config, configErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func Path() string {
|
func Path() string {
|
||||||
if path := os.Getenv("CONTAINERS_CONF"); path != "" {
|
if path := os.Getenv("CONTAINERS_CONF"); path != "" {
|
||||||
return path
|
return path
|
||||||
@ -1289,9 +1097,7 @@ func (c *Config) Write() error {
|
|||||||
// This function is meant to be used for long-running processes that need to reload potential changes made to
|
// This function is meant to be used for long-running processes that need to reload potential changes made to
|
||||||
// the cached containers.conf files.
|
// the cached containers.conf files.
|
||||||
func Reload() (*Config, error) {
|
func Reload() (*Config, error) {
|
||||||
configMutex.Lock()
|
return New(&Options{SetDefault: true})
|
||||||
defer configMutex.Unlock()
|
|
||||||
return defConfig()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) ActiveDestination() (uri, identity string, machine bool, err error) {
|
func (c *Config) ActiveDestination() (uri, identity string, machine bool, err error) {
|
||||||
|
25
vendor/github.com/containers/common/pkg/config/default.go
generated
vendored
25
vendor/github.com/containers/common/pkg/config/default.go
generated
vendored
@ -157,9 +157,11 @@ const (
|
|||||||
DefaultVolumePluginTimeout = 5
|
DefaultVolumePluginTimeout = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultConfig defines the default values from containers.conf.
|
// defaultConfig returns Config with builtin defaults and minimal adjustments
|
||||||
func DefaultConfig() (*Config, error) {
|
// to the current host only. It does not read any config files from the host or
|
||||||
defaultEngineConfig, err := defaultConfigFromMemory()
|
// the environment.
|
||||||
|
func defaultConfig() (*Config, error) {
|
||||||
|
defaultEngineConfig, err := defaultEngineConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -266,9 +268,9 @@ func defaultFarmConfig() FarmConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultConfigFromMemory returns a default engine configuration. Note that the
|
// defaultEngineConfig eturns a default engine configuration. Note that the
|
||||||
// config is different for root and rootless. It also parses the storage.conf.
|
// config is different for root and rootless. It also parses the storage.conf.
|
||||||
func defaultConfigFromMemory() (*EngineConfig, error) {
|
func defaultEngineConfig() (*EngineConfig, error) {
|
||||||
c := new(EngineConfig)
|
c := new(EngineConfig)
|
||||||
tmp, err := defaultTmpDir()
|
tmp, err := defaultTmpDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -653,3 +655,16 @@ func useUserConfigLocations() bool {
|
|||||||
// GetRootlessUID == -1 on Windows, so exclude negative range
|
// GetRootlessUID == -1 on Windows, so exclude negative range
|
||||||
return unshare.GetRootlessUID() > 0
|
return unshare.GetRootlessUID() > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getDefaultImage returns the default machine image stream
|
||||||
|
// On Windows this refers to the Fedora major release number
|
||||||
|
func getDefaultMachineImage() string {
|
||||||
|
return "testing"
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDefaultMachineUser returns the user to use for rootless podman
|
||||||
|
// This is only for the apple, hyperv, and qemu implementations.
|
||||||
|
// WSL's user will be hardcoded in podman to "user"
|
||||||
|
func getDefaultMachineUser() string {
|
||||||
|
return "core"
|
||||||
|
}
|
||||||
|
11
vendor/github.com/containers/common/pkg/config/default_linux.go
generated
vendored
11
vendor/github.com/containers/common/pkg/config/default_linux.go
generated
vendored
@ -17,17 +17,6 @@ func getDefaultCgroupsMode() string {
|
|||||||
return "enabled"
|
return "enabled"
|
||||||
}
|
}
|
||||||
|
|
||||||
// getDefaultMachineImage returns the default machine image stream
|
|
||||||
// On Linux/Mac, this returns the FCOS stream
|
|
||||||
func getDefaultMachineImage() string {
|
|
||||||
return "testing"
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDefaultMachineUser returns the user to use for rootless podman
|
|
||||||
func getDefaultMachineUser() string {
|
|
||||||
return "core"
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDefaultProcessLimits returns the nproc for the current process in ulimits format
|
// getDefaultProcessLimits returns the nproc for the current process in ulimits format
|
||||||
// Note that nfile sometimes cannot be set to unlimited, and the limit is hardcoded
|
// Note that nfile sometimes cannot be set to unlimited, and the limit is hardcoded
|
||||||
// to (oldMaxSize) 1048576 (2^20), see: http://stackoverflow.com/a/1213069/1811501
|
// to (oldMaxSize) 1048576 (2^20), see: http://stackoverflow.com/a/1213069/1811501
|
||||||
|
11
vendor/github.com/containers/common/pkg/config/default_unsupported.go
generated
vendored
11
vendor/github.com/containers/common/pkg/config/default_unsupported.go
generated
vendored
@ -5,17 +5,6 @@ package config
|
|||||||
|
|
||||||
import "os"
|
import "os"
|
||||||
|
|
||||||
// getDefaultMachineImage returns the default machine image stream
|
|
||||||
// On Linux/Mac, this returns the FCOS stream
|
|
||||||
func getDefaultMachineImage() string {
|
|
||||||
return "testing"
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDefaultMachineUser returns the user to use for rootless podman
|
|
||||||
func getDefaultMachineUser() string {
|
|
||||||
return "core"
|
|
||||||
}
|
|
||||||
|
|
||||||
// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
|
// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
|
||||||
func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
|
func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
13
vendor/github.com/containers/common/pkg/config/default_windows.go
generated
vendored
13
vendor/github.com/containers/common/pkg/config/default_windows.go
generated
vendored
@ -2,19 +2,6 @@ package config
|
|||||||
|
|
||||||
import "os"
|
import "os"
|
||||||
|
|
||||||
// getDefaultImage returns the default machine image stream
|
|
||||||
// On Windows this refers to the Fedora major release number
|
|
||||||
func getDefaultMachineImage() string {
|
|
||||||
return "testing"
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDefaultMachineUser returns the user to use for rootless podman
|
|
||||||
// This is only for the hyperv and qemu implementations. WSL's user
|
|
||||||
// will be hardcoded in podman to "user"
|
|
||||||
func getDefaultMachineUser() string {
|
|
||||||
return "core"
|
|
||||||
}
|
|
||||||
|
|
||||||
// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
|
// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
|
||||||
func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
|
func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
95
vendor/github.com/containers/common/pkg/config/modules.go
generated
vendored
Normal file
95
vendor/github.com/containers/common/pkg/config/modules.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/containers/storage/pkg/homedir"
|
||||||
|
"github.com/containers/storage/pkg/unshare"
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The subdirectory for looking up containers.conf modules.
|
||||||
|
const moduleSubdir = "containers/containers.conf.modules"
|
||||||
|
|
||||||
|
// Moving the base paths into variables allows for overriding them in units
|
||||||
|
// tests.
|
||||||
|
var (
|
||||||
|
moduleBaseEtc = "/etc/"
|
||||||
|
moduleBaseUsr = "/usr/share"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadedModules returns absolute paths to loaded containers.conf modules.
|
||||||
|
func (c *Config) LoadedModules() []string {
|
||||||
|
// Required for conmon's callback to Podman's cleanup.
|
||||||
|
// Absolute paths make loading the modules a bit faster.
|
||||||
|
return c.loadedModules
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the specified modules in the options. Return an error if a specific
|
||||||
|
// module cannot be located on the host.
|
||||||
|
func (o *Options) modules() ([]string, error) {
|
||||||
|
if len(o.Modules) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dirs, err := ModuleDirectories()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
configs := make([]string, 0, len(o.Modules))
|
||||||
|
for _, path := range o.Modules {
|
||||||
|
resolved, err := resolveModule(path, dirs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not resolve module %q: %w", path, err)
|
||||||
|
}
|
||||||
|
configs = append(configs, resolved)
|
||||||
|
}
|
||||||
|
|
||||||
|
return configs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModuleDirectories return the directories to load modules from:
|
||||||
|
// 1) XDG_CONFIG_HOME/HOME if rootless
|
||||||
|
// 2) /etc/
|
||||||
|
// 3) /usr/share
|
||||||
|
func ModuleDirectories() ([]string, error) { // Public API for shell completions in Podman
|
||||||
|
modules := []string{
|
||||||
|
filepath.Join(moduleBaseEtc, moduleSubdir),
|
||||||
|
filepath.Join(moduleBaseUsr, moduleSubdir),
|
||||||
|
}
|
||||||
|
|
||||||
|
if !unshare.IsRootless() {
|
||||||
|
return modules, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend the user modules dir.
|
||||||
|
configHome, err := homedir.GetConfigHome()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return append([]string{filepath.Join(configHome, moduleSubdir)}, modules...), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve the specified path to a module.
|
||||||
|
func resolveModule(path string, dirs []string) (string, error) {
|
||||||
|
if filepath.IsAbs(path) {
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
return path, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect all errors to avoid suppressing important errors (e.g.,
|
||||||
|
// permission errors).
|
||||||
|
var multiErr error
|
||||||
|
for _, d := range dirs {
|
||||||
|
candidate := filepath.Join(d, path)
|
||||||
|
_, err := os.Stat(candidate)
|
||||||
|
if err == nil {
|
||||||
|
return candidate, nil
|
||||||
|
}
|
||||||
|
multiErr = multierror.Append(multiErr, err)
|
||||||
|
}
|
||||||
|
return "", multiErr
|
||||||
|
}
|
240
vendor/github.com/containers/common/pkg/config/new.go
generated
vendored
Normal file
240
vendor/github.com/containers/common/pkg/config/new.go
generated
vendored
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cachedConfigError error
|
||||||
|
cachedConfigMutex sync.Mutex
|
||||||
|
cachedConfig *Config
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// FIXME: update code base and tests to use the two constants below.
|
||||||
|
containersConfEnv = "CONTAINERS_CONF"
|
||||||
|
containersConfOverrideEnv = containersConfEnv + "_OVERRIDE"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Options to use when loading a Config via New().
|
||||||
|
type Options struct {
|
||||||
|
// Attempt to load the following config modules.
|
||||||
|
Modules []string
|
||||||
|
|
||||||
|
// Set the loaded config as the default one which can later on be
|
||||||
|
// accessed via Default().
|
||||||
|
SetDefault bool
|
||||||
|
|
||||||
|
// Additional configs to load. An internal only field to make the
|
||||||
|
// behavior observable and testable in unit tests.
|
||||||
|
additionalConfigs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a Config as described in the containers.conf(5) man page.
|
||||||
|
func New(options *Options) (*Config, error) {
|
||||||
|
if options == nil {
|
||||||
|
options = &Options{}
|
||||||
|
} else if options.SetDefault {
|
||||||
|
cachedConfigMutex.Lock()
|
||||||
|
defer cachedConfigMutex.Unlock()
|
||||||
|
}
|
||||||
|
return newLocked(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default returns the default container config. If no default config has been
|
||||||
|
// set yet, a new config will be loaded by New() and set as the default one.
|
||||||
|
// All callers are expected to use the returned Config read only. Changing
|
||||||
|
// data may impact other call sites.
|
||||||
|
func Default() (*Config, error) {
|
||||||
|
cachedConfigMutex.Lock()
|
||||||
|
defer cachedConfigMutex.Unlock()
|
||||||
|
if cachedConfig != nil || cachedConfigError != nil {
|
||||||
|
return cachedConfig, cachedConfigError
|
||||||
|
}
|
||||||
|
cachedConfig, cachedConfigError = newLocked(&Options{SetDefault: true})
|
||||||
|
return cachedConfig, cachedConfigError
|
||||||
|
}
|
||||||
|
|
||||||
|
// A helper function for New() expecting the caller to hold the
|
||||||
|
// cachedConfigMutex if options.SetDefault is set..
|
||||||
|
func newLocked(options *Options) (*Config, error) {
|
||||||
|
// Start with the built-in defaults
|
||||||
|
config, err := defaultConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, gather the system configs and merge them as needed.
|
||||||
|
configs, err := systemConfigs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("finding config on system: %w", err)
|
||||||
|
}
|
||||||
|
for _, path := range configs {
|
||||||
|
// Merge changes in later configs with the previous configs.
|
||||||
|
// Each config file that specified fields, will override the
|
||||||
|
// previous fields.
|
||||||
|
if err = readConfigFromFile(path, config); err != nil {
|
||||||
|
return nil, fmt.Errorf("reading system config %q: %w", path, err)
|
||||||
|
}
|
||||||
|
logrus.Debugf("Merged system config %q", path)
|
||||||
|
logrus.Tracef("%+v", config)
|
||||||
|
}
|
||||||
|
|
||||||
|
modules, err := options.modules()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config.loadedModules = modules
|
||||||
|
|
||||||
|
options.additionalConfigs = append(options.additionalConfigs, modules...)
|
||||||
|
|
||||||
|
// The _OVERRIDE variable _must_ always win. That's a contract we need
|
||||||
|
// to honor (for the Podman CI).
|
||||||
|
if path := os.Getenv(containersConfOverrideEnv); path != "" {
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
return nil, fmt.Errorf("%s file: %w", containersConfOverrideEnv, err)
|
||||||
|
}
|
||||||
|
options.additionalConfigs = append(options.additionalConfigs, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the caller specified a config path to use, then we read it to
|
||||||
|
// override the system defaults.
|
||||||
|
for _, add := range options.additionalConfigs {
|
||||||
|
if add == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// readConfigFromFile reads in container config in the specified
|
||||||
|
// file and then merge changes with the current default.
|
||||||
|
if err := readConfigFromFile(add, config); err != nil {
|
||||||
|
return nil, fmt.Errorf("reading additional config %q: %w", add, err)
|
||||||
|
}
|
||||||
|
logrus.Debugf("Merged additional config %q", add)
|
||||||
|
logrus.Tracef("%+v", config)
|
||||||
|
}
|
||||||
|
config.addCAPPrefix()
|
||||||
|
|
||||||
|
if err := config.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := config.setupEnv(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.SetDefault {
|
||||||
|
cachedConfig = config
|
||||||
|
cachedConfigError = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConfig creates a new Config. It starts with an empty config and, if
|
||||||
|
// specified, merges the config at `userConfigPath` path.
|
||||||
|
//
|
||||||
|
// Deprecated: use new instead.
|
||||||
|
func NewConfig(userConfigPath string) (*Config, error) {
|
||||||
|
return New(&Options{additionalConfigs: []string{userConfigPath}})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the list of configuration files, if they exist in order of hierarchy.
|
||||||
|
// The files are read in order and each new file can/will override previous
|
||||||
|
// file settings.
|
||||||
|
func systemConfigs() (configs []string, finalErr error) {
|
||||||
|
if path := os.Getenv(containersConfEnv); path != "" {
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
return nil, fmt.Errorf("%s file: %w", containersConfEnv, err)
|
||||||
|
}
|
||||||
|
return append(configs, path), nil
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(DefaultContainersConfig); err == nil {
|
||||||
|
configs = append(configs, DefaultContainersConfig)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(OverrideContainersConfig); err == nil {
|
||||||
|
configs = append(configs, OverrideContainersConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
configs, err = addConfigs(OverrideContainersConfig+".d", configs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err := ifRootlessConfigPath()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if path != "" {
|
||||||
|
if _, err := os.Stat(path); err == nil {
|
||||||
|
configs = append(configs, path)
|
||||||
|
}
|
||||||
|
configs, err = addConfigs(path+".d", configs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return configs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// addConfigs will search one level in the config dirPath for config files
|
||||||
|
// If the dirPath does not exist, addConfigs will return nil
|
||||||
|
func addConfigs(dirPath string, configs []string) ([]string, error) {
|
||||||
|
newConfigs := []string{}
|
||||||
|
|
||||||
|
err := filepath.WalkDir(dirPath,
|
||||||
|
// WalkFunc to read additional configs
|
||||||
|
func(path string, d fs.DirEntry, err error) error {
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
// return error (could be a permission problem)
|
||||||
|
return err
|
||||||
|
case d.IsDir():
|
||||||
|
if path != dirPath {
|
||||||
|
// make sure to not recurse into sub-directories
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
// ignore directories
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
// only add *.conf files
|
||||||
|
if strings.HasSuffix(path, ".conf") {
|
||||||
|
newConfigs = append(newConfigs, path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
sort.Strings(newConfigs)
|
||||||
|
return append(configs, newConfigs...), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// readConfigFromFile reads the specified config file at `path` and attempts to
|
||||||
|
// unmarshal its content into a Config. The config param specifies the previous
|
||||||
|
// default config. If the path, only specifies a few fields in the Toml file
|
||||||
|
// the defaults from the config parameter will be used for all other fields.
|
||||||
|
func readConfigFromFile(path string, config *Config) error {
|
||||||
|
logrus.Tracef("Reading configuration file %q", path)
|
||||||
|
meta, err := toml.DecodeFile(path, config)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("decode configuration %v: %w", path, err)
|
||||||
|
}
|
||||||
|
keys := meta.Undecoded()
|
||||||
|
if len(keys) > 0 {
|
||||||
|
logrus.Debugf("Failed to decode the keys %q from %q.", keys, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
33
vendor/github.com/pkg/sftp/attrs.go
generated
vendored
33
vendor/github.com/pkg/sftp/attrs.go
generated
vendored
@ -1,7 +1,7 @@
|
|||||||
package sftp
|
package sftp
|
||||||
|
|
||||||
// ssh_FXP_ATTRS support
|
// ssh_FXP_ATTRS support
|
||||||
// see http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-5
|
// see https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-5
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
@ -69,6 +69,20 @@ func fileInfoFromStat(stat *FileStat, name string) os.FileInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileInfoUidGid extends os.FileInfo and adds callbacks for Uid and Gid retrieval,
|
||||||
|
// as an alternative to *syscall.Stat_t objects on unix systems.
|
||||||
|
type FileInfoUidGid interface {
|
||||||
|
os.FileInfo
|
||||||
|
Uid() uint32
|
||||||
|
Gid() uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileInfoUidGid extends os.FileInfo and adds a callbacks for extended data retrieval.
|
||||||
|
type FileInfoExtendedData interface {
|
||||||
|
os.FileInfo
|
||||||
|
Extended() []StatExtended
|
||||||
|
}
|
||||||
|
|
||||||
func fileStatFromInfo(fi os.FileInfo) (uint32, *FileStat) {
|
func fileStatFromInfo(fi os.FileInfo) (uint32, *FileStat) {
|
||||||
mtime := fi.ModTime().Unix()
|
mtime := fi.ModTime().Unix()
|
||||||
atime := mtime
|
atime := mtime
|
||||||
@ -86,5 +100,22 @@ func fileStatFromInfo(fi os.FileInfo) (uint32, *FileStat) {
|
|||||||
// os specific file stat decoding
|
// os specific file stat decoding
|
||||||
fileStatFromInfoOs(fi, &flags, fileStat)
|
fileStatFromInfoOs(fi, &flags, fileStat)
|
||||||
|
|
||||||
|
// The call above will include the sshFileXferAttrUIDGID in case
|
||||||
|
// the os.FileInfo can be casted to *syscall.Stat_t on unix.
|
||||||
|
// If fi implements FileInfoUidGid, retrieve Uid, Gid from it instead.
|
||||||
|
if fiExt, ok := fi.(FileInfoUidGid); ok {
|
||||||
|
flags |= sshFileXferAttrUIDGID
|
||||||
|
fileStat.UID = fiExt.Uid()
|
||||||
|
fileStat.GID = fiExt.Gid()
|
||||||
|
}
|
||||||
|
|
||||||
|
// if fi implements FileInfoExtendedData, retrieve extended data from it
|
||||||
|
if fiExt, ok := fi.(FileInfoExtendedData); ok {
|
||||||
|
fileStat.Extended = fiExt.Extended()
|
||||||
|
if len(fileStat.Extended) > 0 {
|
||||||
|
flags |= sshFileXferAttrExtended
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return flags, fileStat
|
return flags, fileStat
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/pkg/sftp/attrs_stubs.go
generated
vendored
1
vendor/github.com/pkg/sftp/attrs_stubs.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build plan9 || windows || android
|
||||||
// +build plan9 windows android
|
// +build plan9 windows android
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
1
vendor/github.com/pkg/sftp/attrs_unix.go
generated
vendored
1
vendor/github.com/pkg/sftp/attrs_unix.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build darwin || dragonfly || freebsd || (!android && linux) || netbsd || openbsd || solaris || aix || js
|
||||||
// +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris aix js
|
// +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris aix js
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
65
vendor/github.com/pkg/sftp/client.go
generated
vendored
65
vendor/github.com/pkg/sftp/client.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
@ -226,15 +227,22 @@ func NewClientPipe(rd io.Reader, wr io.WriteCloser, opts ...ClientOption) (*Clie
|
|||||||
|
|
||||||
if err := sftp.sendInit(); err != nil {
|
if err := sftp.sendInit(); err != nil {
|
||||||
wr.Close()
|
wr.Close()
|
||||||
return nil, err
|
return nil, fmt.Errorf("error sending init packet to server: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sftp.recvVersion(); err != nil {
|
if err := sftp.recvVersion(); err != nil {
|
||||||
wr.Close()
|
wr.Close()
|
||||||
return nil, err
|
return nil, fmt.Errorf("error receiving version packet from server: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sftp.clientConn.wg.Add(1)
|
sftp.clientConn.wg.Add(1)
|
||||||
go sftp.loop()
|
go func() {
|
||||||
|
defer sftp.clientConn.wg.Done()
|
||||||
|
|
||||||
|
if err := sftp.clientConn.recv(); err != nil {
|
||||||
|
sftp.clientConn.broadcastErr(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
return sftp, nil
|
return sftp, nil
|
||||||
}
|
}
|
||||||
@ -251,11 +259,11 @@ func (c *Client) Create(path string) (*File, error) {
|
|||||||
return c.open(path, flags(os.O_RDWR|os.O_CREATE|os.O_TRUNC))
|
return c.open(path, flags(os.O_RDWR|os.O_CREATE|os.O_TRUNC))
|
||||||
}
|
}
|
||||||
|
|
||||||
const sftpProtocolVersion = 3 // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
|
const sftpProtocolVersion = 3 // https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
|
||||||
|
|
||||||
func (c *Client) sendInit() error {
|
func (c *Client) sendInit() error {
|
||||||
return c.clientConn.conn.sendPacket(&sshFxInitPacket{
|
return c.clientConn.conn.sendPacket(&sshFxInitPacket{
|
||||||
Version: sftpProtocolVersion, // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
|
Version: sftpProtocolVersion, // https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,8 +275,13 @@ func (c *Client) nextID() uint32 {
|
|||||||
func (c *Client) recvVersion() error {
|
func (c *Client) recvVersion() error {
|
||||||
typ, data, err := c.recvPacket(0)
|
typ, data, err := c.recvPacket(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
return fmt.Errorf("server unexpectedly closed connection: %w", io.ErrUnexpectedEOF)
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if typ != sshFxpVersion {
|
if typ != sshFxpVersion {
|
||||||
return &unexpectedPacketErr{sshFxpVersion, typ}
|
return &unexpectedPacketErr{sshFxpVersion, typ}
|
||||||
}
|
}
|
||||||
@ -277,6 +290,7 @@ func (c *Client) recvVersion() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if version != sftpProtocolVersion {
|
if version != sftpProtocolVersion {
|
||||||
return &unexpectedVersionErr{sftpProtocolVersion, version}
|
return &unexpectedVersionErr{sftpProtocolVersion, version}
|
||||||
}
|
}
|
||||||
@ -910,6 +924,45 @@ func (c *Client) MkdirAll(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveAll delete files recursively in the directory and Recursively delete subdirectories.
|
||||||
|
// An error will be returned if no file or directory with the specified path exists
|
||||||
|
func (c *Client) RemoveAll(path string) error {
|
||||||
|
|
||||||
|
// Get the file/directory information
|
||||||
|
fi, err := c.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.IsDir() {
|
||||||
|
// Delete files recursively in the directory
|
||||||
|
files, err := c.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if file.IsDir() {
|
||||||
|
// Recursively delete subdirectories
|
||||||
|
err = c.RemoveAll(path + "/" + file.Name())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Delete individual files
|
||||||
|
err = c.Remove(path + "/" + file.Name())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Remove(path)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// File represents a remote file.
|
// File represents a remote file.
|
||||||
type File struct {
|
type File struct {
|
||||||
c *Client
|
c *Client
|
||||||
@ -1660,7 +1713,7 @@ func (f *File) ReadFromWithConcurrency(r io.Reader, concurrency int) (read int64
|
|||||||
Handle: f.handle,
|
Handle: f.handle,
|
||||||
Offset: uint64(off),
|
Offset: uint64(off),
|
||||||
Length: uint32(n),
|
Length: uint32(n),
|
||||||
Data: b,
|
Data: b[:n],
|
||||||
})
|
})
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
12
vendor/github.com/pkg/sftp/conn.go
generated
vendored
12
vendor/github.com/pkg/sftp/conn.go
generated
vendored
@ -18,7 +18,9 @@ type conn struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the orderID is used in server mode if the allocator is enabled.
|
// the orderID is used in server mode if the allocator is enabled.
|
||||||
// For the client mode just pass 0
|
// For the client mode just pass 0.
|
||||||
|
// It returns io.EOF if the connection is closed and
|
||||||
|
// there are no more packets to read.
|
||||||
func (c *conn) recvPacket(orderID uint32) (uint8, []byte, error) {
|
func (c *conn) recvPacket(orderID uint32) (uint8, []byte, error) {
|
||||||
return recvPacket(c, c.alloc, orderID)
|
return recvPacket(c, c.alloc, orderID)
|
||||||
}
|
}
|
||||||
@ -61,14 +63,6 @@ func (c *clientConn) Close() error {
|
|||||||
return c.conn.Close()
|
return c.conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientConn) loop() {
|
|
||||||
defer c.wg.Done()
|
|
||||||
err := c.recv()
|
|
||||||
if err != nil {
|
|
||||||
c.broadcastErr(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// recv continuously reads from the server and forwards responses to the
|
// recv continuously reads from the server and forwards responses to the
|
||||||
// appropriate channel.
|
// appropriate channel.
|
||||||
func (c *clientConn) recv() error {
|
func (c *clientConn) recv() error {
|
||||||
|
1
vendor/github.com/pkg/sftp/debug.go
generated
vendored
1
vendor/github.com/pkg/sftp/debug.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build debug
|
||||||
// +build debug
|
// +build debug
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
1
vendor/github.com/pkg/sftp/fuzz.go
generated
vendored
1
vendor/github.com/pkg/sftp/fuzz.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build gofuzz
|
||||||
// +build gofuzz
|
// +build gofuzz
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
117
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/attrs.go
generated
vendored
117
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/attrs.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
// Attributes related flags.
|
// Attributes related flags.
|
||||||
const (
|
const (
|
||||||
@ -12,7 +12,7 @@ const (
|
|||||||
|
|
||||||
// Attributes defines the file attributes type defined in draft-ietf-secsh-filexfer-02
|
// Attributes defines the file attributes type defined in draft-ietf-secsh-filexfer-02
|
||||||
//
|
//
|
||||||
// Defined in: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-5
|
// Defined in: https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-5
|
||||||
type Attributes struct {
|
type Attributes struct {
|
||||||
Flags uint32
|
Flags uint32
|
||||||
|
|
||||||
@ -116,32 +116,32 @@ func (a *Attributes) Len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MarshalInto marshals e onto the end of the given Buffer.
|
// MarshalInto marshals e onto the end of the given Buffer.
|
||||||
func (a *Attributes) MarshalInto(b *Buffer) {
|
func (a *Attributes) MarshalInto(buf *Buffer) {
|
||||||
b.AppendUint32(a.Flags)
|
buf.AppendUint32(a.Flags)
|
||||||
|
|
||||||
if a.Flags&AttrSize != 0 {
|
if a.Flags&AttrSize != 0 {
|
||||||
b.AppendUint64(a.Size)
|
buf.AppendUint64(a.Size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Flags&AttrUIDGID != 0 {
|
if a.Flags&AttrUIDGID != 0 {
|
||||||
b.AppendUint32(a.UID)
|
buf.AppendUint32(a.UID)
|
||||||
b.AppendUint32(a.GID)
|
buf.AppendUint32(a.GID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Flags&AttrPermissions != 0 {
|
if a.Flags&AttrPermissions != 0 {
|
||||||
b.AppendUint32(uint32(a.Permissions))
|
buf.AppendUint32(uint32(a.Permissions))
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Flags&AttrACModTime != 0 {
|
if a.Flags&AttrACModTime != 0 {
|
||||||
b.AppendUint32(a.ATime)
|
buf.AppendUint32(a.ATime)
|
||||||
b.AppendUint32(a.MTime)
|
buf.AppendUint32(a.MTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Flags&AttrExtended != 0 {
|
if a.Flags&AttrExtended != 0 {
|
||||||
b.AppendUint32(uint32(len(a.ExtendedAttributes)))
|
buf.AppendUint32(uint32(len(a.ExtendedAttributes)))
|
||||||
|
|
||||||
for _, ext := range a.ExtendedAttributes {
|
for _, ext := range a.ExtendedAttributes {
|
||||||
ext.MarshalInto(b)
|
ext.MarshalInto(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,74 +156,51 @@ func (a *Attributes) MarshalBinary() ([]byte, error) {
|
|||||||
// UnmarshalFrom unmarshals an Attributes from the given Buffer into e.
|
// UnmarshalFrom unmarshals an Attributes from the given Buffer into e.
|
||||||
//
|
//
|
||||||
// NOTE: The values of fields not covered in the a.Flags are explicitly undefined.
|
// NOTE: The values of fields not covered in the a.Flags are explicitly undefined.
|
||||||
func (a *Attributes) UnmarshalFrom(b *Buffer) (err error) {
|
func (a *Attributes) UnmarshalFrom(buf *Buffer) (err error) {
|
||||||
flags, err := b.ConsumeUint32()
|
flags := buf.ConsumeUint32()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.XXX_UnmarshalByFlags(flags, b)
|
return a.XXX_UnmarshalByFlags(flags, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX_UnmarshalByFlags uses the pre-existing a.Flags field to determine which fields to decode.
|
// XXX_UnmarshalByFlags uses the pre-existing a.Flags field to determine which fields to decode.
|
||||||
// DO NOT USE THIS: it is an anti-corruption function to implement existing internal usage in pkg/sftp.
|
// DO NOT USE THIS: it is an anti-corruption function to implement existing internal usage in pkg/sftp.
|
||||||
// This function is not a part of any compatibility promise.
|
// This function is not a part of any compatibility promise.
|
||||||
func (a *Attributes) XXX_UnmarshalByFlags(flags uint32, b *Buffer) (err error) {
|
func (a *Attributes) XXX_UnmarshalByFlags(flags uint32, buf *Buffer) (err error) {
|
||||||
a.Flags = flags
|
a.Flags = flags
|
||||||
|
|
||||||
// Short-circuit dummy attributes.
|
// Short-circuit dummy attributes.
|
||||||
if a.Flags == 0 {
|
if a.Flags == 0 {
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Flags&AttrSize != 0 {
|
if a.Flags&AttrSize != 0 {
|
||||||
if a.Size, err = b.ConsumeUint64(); err != nil {
|
a.Size = buf.ConsumeUint64()
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Flags&AttrUIDGID != 0 {
|
if a.Flags&AttrUIDGID != 0 {
|
||||||
if a.UID, err = b.ConsumeUint32(); err != nil {
|
a.UID = buf.ConsumeUint32()
|
||||||
return err
|
a.GID = buf.ConsumeUint32()
|
||||||
}
|
|
||||||
|
|
||||||
if a.GID, err = b.ConsumeUint32(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Flags&AttrPermissions != 0 {
|
if a.Flags&AttrPermissions != 0 {
|
||||||
m, err := b.ConsumeUint32()
|
a.Permissions = FileMode(buf.ConsumeUint32())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Permissions = FileMode(m)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Flags&AttrACModTime != 0 {
|
if a.Flags&AttrACModTime != 0 {
|
||||||
if a.ATime, err = b.ConsumeUint32(); err != nil {
|
a.ATime = buf.ConsumeUint32()
|
||||||
return err
|
a.MTime = buf.ConsumeUint32()
|
||||||
}
|
|
||||||
|
|
||||||
if a.MTime, err = b.ConsumeUint32(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Flags&AttrExtended != 0 {
|
if a.Flags&AttrExtended != 0 {
|
||||||
count, err := b.ConsumeUint32()
|
count := buf.ConsumeCount()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
a.ExtendedAttributes = make([]ExtendedAttribute, count)
|
a.ExtendedAttributes = make([]ExtendedAttribute, count)
|
||||||
for i := range a.ExtendedAttributes {
|
for i := range a.ExtendedAttributes {
|
||||||
a.ExtendedAttributes[i].UnmarshalFrom(b)
|
a.ExtendedAttributes[i].UnmarshalFrom(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalBinary decodes the binary encoding of Attributes into e.
|
// UnmarshalBinary decodes the binary encoding of Attributes into e.
|
||||||
@ -233,7 +210,7 @@ func (a *Attributes) UnmarshalBinary(data []byte) error {
|
|||||||
|
|
||||||
// ExtendedAttribute defines the extended file attribute type defined in draft-ietf-secsh-filexfer-02
|
// ExtendedAttribute defines the extended file attribute type defined in draft-ietf-secsh-filexfer-02
|
||||||
//
|
//
|
||||||
// Defined in: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-5
|
// Defined in: https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-5
|
||||||
type ExtendedAttribute struct {
|
type ExtendedAttribute struct {
|
||||||
Type string
|
Type string
|
||||||
Data string
|
Data string
|
||||||
@ -245,9 +222,9 @@ func (e *ExtendedAttribute) Len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MarshalInto marshals e onto the end of the given Buffer.
|
// MarshalInto marshals e onto the end of the given Buffer.
|
||||||
func (e *ExtendedAttribute) MarshalInto(b *Buffer) {
|
func (e *ExtendedAttribute) MarshalInto(buf *Buffer) {
|
||||||
b.AppendString(e.Type)
|
buf.AppendString(e.Type)
|
||||||
b.AppendString(e.Data)
|
buf.AppendString(e.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalBinary returns e as the binary encoding of e.
|
// MarshalBinary returns e as the binary encoding of e.
|
||||||
@ -258,16 +235,13 @@ func (e *ExtendedAttribute) MarshalBinary() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalFrom unmarshals an ExtendedAattribute from the given Buffer into e.
|
// UnmarshalFrom unmarshals an ExtendedAattribute from the given Buffer into e.
|
||||||
func (e *ExtendedAttribute) UnmarshalFrom(b *Buffer) (err error) {
|
func (e *ExtendedAttribute) UnmarshalFrom(buf *Buffer) (err error) {
|
||||||
if e.Type, err = b.ConsumeString(); err != nil {
|
*e = ExtendedAttribute{
|
||||||
return err
|
Type: buf.ConsumeString(),
|
||||||
|
Data: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Data, err = b.ConsumeString(); err != nil {
|
return buf.Err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalBinary decodes the binary encoding of ExtendedAttribute into e.
|
// UnmarshalBinary decodes the binary encoding of ExtendedAttribute into e.
|
||||||
@ -290,11 +264,11 @@ func (e *NameEntry) Len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MarshalInto marshals e onto the end of the given Buffer.
|
// MarshalInto marshals e onto the end of the given Buffer.
|
||||||
func (e *NameEntry) MarshalInto(b *Buffer) {
|
func (e *NameEntry) MarshalInto(buf *Buffer) {
|
||||||
b.AppendString(e.Filename)
|
buf.AppendString(e.Filename)
|
||||||
b.AppendString(e.Longname)
|
buf.AppendString(e.Longname)
|
||||||
|
|
||||||
e.Attrs.MarshalInto(b)
|
e.Attrs.MarshalInto(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalBinary returns e as the binary encoding of e.
|
// MarshalBinary returns e as the binary encoding of e.
|
||||||
@ -307,16 +281,13 @@ func (e *NameEntry) MarshalBinary() ([]byte, error) {
|
|||||||
// UnmarshalFrom unmarshals an NameEntry from the given Buffer into e.
|
// UnmarshalFrom unmarshals an NameEntry from the given Buffer into e.
|
||||||
//
|
//
|
||||||
// NOTE: The values of fields not covered in the a.Flags are explicitly undefined.
|
// NOTE: The values of fields not covered in the a.Flags are explicitly undefined.
|
||||||
func (e *NameEntry) UnmarshalFrom(b *Buffer) (err error) {
|
func (e *NameEntry) UnmarshalFrom(buf *Buffer) (err error) {
|
||||||
if e.Filename, err = b.ConsumeString(); err != nil {
|
*e = NameEntry{
|
||||||
return err
|
Filename: buf.ConsumeString(),
|
||||||
|
Longname: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Longname, err = b.ConsumeString(); err != nil {
|
return e.Attrs.UnmarshalFrom(buf)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.Attrs.UnmarshalFrom(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalBinary decodes the binary encoding of NameEntry into e.
|
// UnmarshalBinary decodes the binary encoding of NameEntry into e.
|
||||||
|
153
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/buffer.go
generated
vendored
153
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/buffer.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@ -17,6 +17,7 @@ var (
|
|||||||
type Buffer struct {
|
type Buffer struct {
|
||||||
b []byte
|
b []byte
|
||||||
off int
|
off int
|
||||||
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBuffer creates and initializes a new buffer using buf as its initial contents.
|
// NewBuffer creates and initializes a new buffer using buf as its initial contents.
|
||||||
@ -51,14 +52,17 @@ func (b *Buffer) Cap() int { return cap(b.b) }
|
|||||||
|
|
||||||
// Reset resets the buffer to be empty, but it retains the underlying storage for use by future Appends.
|
// Reset resets the buffer to be empty, but it retains the underlying storage for use by future Appends.
|
||||||
func (b *Buffer) Reset() {
|
func (b *Buffer) Reset() {
|
||||||
b.b = b.b[:0]
|
*b = Buffer{
|
||||||
b.off = 0
|
b: b.b[:0],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartPacket resets and initializes the buffer to be ready to start marshaling a packet into.
|
// StartPacket resets and initializes the buffer to be ready to start marshaling a packet into.
|
||||||
// It truncates the buffer, reserves space for uint32(length), then appends the given packetType and requestID.
|
// It truncates the buffer, reserves space for uint32(length), then appends the given packetType and requestID.
|
||||||
func (b *Buffer) StartPacket(packetType PacketType, requestID uint32) {
|
func (b *Buffer) StartPacket(packetType PacketType, requestID uint32) {
|
||||||
b.b, b.off = append(b.b[:0], make([]byte, 4)...), 0
|
*b = Buffer{
|
||||||
|
b: append(b.b[:0], make([]byte, 4)...),
|
||||||
|
}
|
||||||
|
|
||||||
b.AppendUint8(uint8(packetType))
|
b.AppendUint8(uint8(packetType))
|
||||||
b.AppendUint32(requestID)
|
b.AppendUint32(requestID)
|
||||||
@ -81,15 +85,21 @@ func (b *Buffer) Packet(payload []byte) (header, payloadPassThru []byte, err err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConsumeUint8 consumes a single byte from the buffer.
|
// ConsumeUint8 consumes a single byte from the buffer.
|
||||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||||
func (b *Buffer) ConsumeUint8() (uint8, error) {
|
func (b *Buffer) ConsumeUint8() uint8 {
|
||||||
|
if b.Err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
if b.Len() < 1 {
|
if b.Len() < 1 {
|
||||||
return 0, ErrShortPacket
|
b.off = len(b.b)
|
||||||
|
b.Err = ErrShortPacket
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var v uint8
|
var v uint8
|
||||||
v, b.off = b.b[b.off], b.off+1
|
v, b.off = b.b[b.off], b.off+1
|
||||||
return v, nil
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendUint8 appends a single byte into the buffer.
|
// AppendUint8 appends a single byte into the buffer.
|
||||||
@ -98,14 +108,9 @@ func (b *Buffer) AppendUint8(v uint8) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConsumeBool consumes a single byte from the buffer, and returns true if that byte is non-zero.
|
// ConsumeBool consumes a single byte from the buffer, and returns true if that byte is non-zero.
|
||||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||||
func (b *Buffer) ConsumeBool() (bool, error) {
|
func (b *Buffer) ConsumeBool() bool {
|
||||||
v, err := b.ConsumeUint8()
|
return b.ConsumeUint8() != 0
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return v != 0, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendBool appends a single bool into the buffer.
|
// AppendBool appends a single bool into the buffer.
|
||||||
@ -119,15 +124,21 @@ func (b *Buffer) AppendBool(v bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConsumeUint16 consumes a single uint16 from the buffer, in network byte order (big-endian).
|
// ConsumeUint16 consumes a single uint16 from the buffer, in network byte order (big-endian).
|
||||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||||
func (b *Buffer) ConsumeUint16() (uint16, error) {
|
func (b *Buffer) ConsumeUint16() uint16 {
|
||||||
|
if b.Err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
if b.Len() < 2 {
|
if b.Len() < 2 {
|
||||||
return 0, ErrShortPacket
|
b.off = len(b.b)
|
||||||
|
b.Err = ErrShortPacket
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
v := binary.BigEndian.Uint16(b.b[b.off:])
|
v := binary.BigEndian.Uint16(b.b[b.off:])
|
||||||
b.off += 2
|
b.off += 2
|
||||||
return v, nil
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendUint16 appends single uint16 into the buffer, in network byte order (big-endian).
|
// AppendUint16 appends single uint16 into the buffer, in network byte order (big-endian).
|
||||||
@ -146,15 +157,21 @@ func unmarshalUint32(b []byte) uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConsumeUint32 consumes a single uint32 from the buffer, in network byte order (big-endian).
|
// ConsumeUint32 consumes a single uint32 from the buffer, in network byte order (big-endian).
|
||||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||||
func (b *Buffer) ConsumeUint32() (uint32, error) {
|
func (b *Buffer) ConsumeUint32() uint32 {
|
||||||
|
if b.Err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
if b.Len() < 4 {
|
if b.Len() < 4 {
|
||||||
return 0, ErrShortPacket
|
b.off = len(b.b)
|
||||||
|
b.Err = ErrShortPacket
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
v := binary.BigEndian.Uint32(b.b[b.off:])
|
v := binary.BigEndian.Uint32(b.b[b.off:])
|
||||||
b.off += 4
|
b.off += 4
|
||||||
return v, nil
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendUint32 appends a single uint32 into the buffer, in network byte order (big-endian).
|
// AppendUint32 appends a single uint32 into the buffer, in network byte order (big-endian).
|
||||||
@ -167,16 +184,33 @@ func (b *Buffer) AppendUint32(v uint32) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConsumeCount consumes a single uint32 count from the buffer, in network byte order (big-endian) as an int.
|
||||||
|
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||||
|
func (b *Buffer) ConsumeCount() int {
|
||||||
|
return int(b.ConsumeUint32())
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendCount appends a single int length as a uint32 into the buffer, in network byte order (big-endian).
|
||||||
|
func (b *Buffer) AppendCount(v int) {
|
||||||
|
b.AppendUint32(uint32(v))
|
||||||
|
}
|
||||||
|
|
||||||
// ConsumeUint64 consumes a single uint64 from the buffer, in network byte order (big-endian).
|
// ConsumeUint64 consumes a single uint64 from the buffer, in network byte order (big-endian).
|
||||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||||
func (b *Buffer) ConsumeUint64() (uint64, error) {
|
func (b *Buffer) ConsumeUint64() uint64 {
|
||||||
|
if b.Err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
if b.Len() < 8 {
|
if b.Len() < 8 {
|
||||||
return 0, ErrShortPacket
|
b.off = len(b.b)
|
||||||
|
b.Err = ErrShortPacket
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
v := binary.BigEndian.Uint64(b.b[b.off:])
|
v := binary.BigEndian.Uint64(b.b[b.off:])
|
||||||
b.off += 8
|
b.off += 8
|
||||||
return v, nil
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendUint64 appends a single uint64 into the buffer, in network byte order (big-endian).
|
// AppendUint64 appends a single uint64 into the buffer, in network byte order (big-endian).
|
||||||
@ -194,14 +228,9 @@ func (b *Buffer) AppendUint64(v uint64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConsumeInt64 consumes a single int64 from the buffer, in network byte order (big-endian) with two’s complement.
|
// ConsumeInt64 consumes a single int64 from the buffer, in network byte order (big-endian) with two’s complement.
|
||||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||||
func (b *Buffer) ConsumeInt64() (int64, error) {
|
func (b *Buffer) ConsumeInt64() int64 {
|
||||||
u, err := b.ConsumeUint64()
|
return int64(b.ConsumeUint64())
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return int64(u), err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendInt64 appends a single int64 into the buffer, in network byte order (big-endian) with two’s complement.
|
// AppendInt64 appends a single int64 into the buffer, in network byte order (big-endian) with two’s complement.
|
||||||
@ -211,29 +240,52 @@ func (b *Buffer) AppendInt64(v int64) {
|
|||||||
|
|
||||||
// ConsumeByteSlice consumes a single string of raw binary data from the buffer.
|
// ConsumeByteSlice consumes a single string of raw binary data from the buffer.
|
||||||
// A string is a uint32 length, followed by that number of raw bytes.
|
// A string is a uint32 length, followed by that number of raw bytes.
|
||||||
// If the buffer does not have enough data, or defines a length larger than available, it will return ErrShortPacket.
|
// If the buffer does not have enough data, or defines a length larger than available, it will set Err to ErrShortPacket.
|
||||||
//
|
//
|
||||||
// The returned slice aliases the buffer contents, and is valid only as long as the buffer is not reused
|
// The returned slice aliases the buffer contents, and is valid only as long as the buffer is not reused
|
||||||
// (that is, only until the next call to Reset, PutLength, StartPacket, or UnmarshalBinary).
|
// (that is, only until the next call to Reset, PutLength, StartPacket, or UnmarshalBinary).
|
||||||
//
|
//
|
||||||
// In no case will any Consume calls return overlapping slice aliases,
|
// In no case will any Consume calls return overlapping slice aliases,
|
||||||
// and Append calls are guaranteed to not disturb this slice alias.
|
// and Append calls are guaranteed to not disturb this slice alias.
|
||||||
func (b *Buffer) ConsumeByteSlice() ([]byte, error) {
|
func (b *Buffer) ConsumeByteSlice() []byte {
|
||||||
length, err := b.ConsumeUint32()
|
length := int(b.ConsumeUint32())
|
||||||
if err != nil {
|
if b.Err != nil {
|
||||||
return nil, err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Len() < int(length) {
|
if b.Len() < length || length < 0 {
|
||||||
return nil, ErrShortPacket
|
b.off = len(b.b)
|
||||||
|
b.Err = ErrShortPacket
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
v := b.b[b.off:]
|
v := b.b[b.off:]
|
||||||
if len(v) > int(length) {
|
if len(v) > length || cap(v) > length {
|
||||||
v = v[:length:length]
|
v = v[:length:length]
|
||||||
}
|
}
|
||||||
b.off += int(length)
|
b.off += int(length)
|
||||||
return v, nil
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsumeByteSliceCopy consumes a single string of raw binary data as a copy from the buffer.
|
||||||
|
// A string is a uint32 length, followed by that number of raw bytes.
|
||||||
|
// If the buffer does not have enough data, or defines a length larger than available, it will set Err to ErrShortPacket.
|
||||||
|
//
|
||||||
|
// The returned slice does not alias any buffer contents,
|
||||||
|
// and will therefore be valid even if the buffer is later reused.
|
||||||
|
//
|
||||||
|
// If hint has sufficient capacity to hold the data, it will be reused and overwritten,
|
||||||
|
// otherwise a new backing slice will be allocated and returned.
|
||||||
|
func (b *Buffer) ConsumeByteSliceCopy(hint []byte) []byte {
|
||||||
|
data := b.ConsumeByteSlice()
|
||||||
|
|
||||||
|
if grow := len(data) - len(hint); grow > 0 {
|
||||||
|
hint = append(hint, make([]byte, grow)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
n := copy(hint, data)
|
||||||
|
hint = hint[:n]
|
||||||
|
return hint
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendByteSlice appends a single string of raw binary data into the buffer.
|
// AppendByteSlice appends a single string of raw binary data into the buffer.
|
||||||
@ -245,17 +297,12 @@ func (b *Buffer) AppendByteSlice(v []byte) {
|
|||||||
|
|
||||||
// ConsumeString consumes a single string of binary data from the buffer.
|
// ConsumeString consumes a single string of binary data from the buffer.
|
||||||
// A string is a uint32 length, followed by that number of raw bytes.
|
// A string is a uint32 length, followed by that number of raw bytes.
|
||||||
// If the buffer does not have enough data, or defines a length larger than available, it will return ErrShortPacket.
|
// If the buffer does not have enough data, or defines a length larger than available, it will set Err to ErrShortPacket.
|
||||||
//
|
//
|
||||||
// NOTE: Go implicitly assumes that strings contain UTF-8 encoded data.
|
// NOTE: Go implicitly assumes that strings contain UTF-8 encoded data.
|
||||||
// All caveats on using arbitrary binary data in Go strings applies.
|
// All caveats on using arbitrary binary data in Go strings applies.
|
||||||
func (b *Buffer) ConsumeString() (string, error) {
|
func (b *Buffer) ConsumeString() string {
|
||||||
v, err := b.ConsumeByteSlice()
|
return string(b.ConsumeByteSlice())
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(v), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendString appends a single string of binary data into the buffer.
|
// AppendString appends a single string of binary data into the buffer.
|
||||||
|
7
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/extended_packets.go
generated
vendored
7
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/extended_packets.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding"
|
"encoding"
|
||||||
@ -86,8 +86,9 @@ func (p *ExtendedPacket) MarshalPacket(reqid uint32, b []byte) (header, payload
|
|||||||
// If the extension has not been registered, then a new Buffer will be allocated.
|
// If the extension has not been registered, then a new Buffer will be allocated.
|
||||||
// Then the request-specific-data will be unmarshaled from the rest of the buffer.
|
// Then the request-specific-data will be unmarshaled from the rest of the buffer.
|
||||||
func (p *ExtendedPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *ExtendedPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.ExtendedRequest, err = buf.ConsumeString(); err != nil {
|
p.ExtendedRequest = buf.ConsumeString()
|
||||||
return err
|
if buf.Err != nil {
|
||||||
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Data == nil {
|
if p.Data == nil {
|
||||||
|
13
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/extensions.go
generated
vendored
13
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/extensions.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
// ExtensionPair defines the extension-pair type defined in draft-ietf-secsh-filexfer-13.
|
// ExtensionPair defines the extension-pair type defined in draft-ietf-secsh-filexfer-13.
|
||||||
// This type is backwards-compatible with how draft-ietf-secsh-filexfer-02 defines extensions.
|
// This type is backwards-compatible with how draft-ietf-secsh-filexfer-02 defines extensions.
|
||||||
@ -29,15 +29,12 @@ func (e *ExtensionPair) MarshalBinary() ([]byte, error) {
|
|||||||
|
|
||||||
// UnmarshalFrom unmarshals an ExtensionPair from the given Buffer into e.
|
// UnmarshalFrom unmarshals an ExtensionPair from the given Buffer into e.
|
||||||
func (e *ExtensionPair) UnmarshalFrom(buf *Buffer) (err error) {
|
func (e *ExtensionPair) UnmarshalFrom(buf *Buffer) (err error) {
|
||||||
if e.Name, err = buf.ConsumeString(); err != nil {
|
*e = ExtensionPair{
|
||||||
return err
|
Name: buf.ConsumeString(),
|
||||||
|
Data: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Data, err = buf.ConsumeString(); err != nil {
|
return buf.Err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalBinary decodes the binary encoding of ExtensionPair into e.
|
// UnmarshalBinary decodes the binary encoding of ExtensionPair into e.
|
||||||
|
4
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/filexfer.go
generated
vendored
4
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/filexfer.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// Package filexfer implements the wire encoding for secsh-filexfer as described in https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
|
// Package sshfx implements the wire encoding for secsh-filexfer as described in https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
|
||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
// PacketMarshaller narrowly defines packets that will only be transmitted.
|
// PacketMarshaller narrowly defines packets that will only be transmitted.
|
||||||
//
|
//
|
||||||
|
18
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/fx.go
generated
vendored
18
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/fx.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -10,7 +10,7 @@ type Status uint32
|
|||||||
// Defines the various SSH_FX_* values.
|
// Defines the various SSH_FX_* values.
|
||||||
const (
|
const (
|
||||||
// see draft-ietf-secsh-filexfer-02
|
// see draft-ietf-secsh-filexfer-02
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-7
|
||||||
StatusOK = Status(iota)
|
StatusOK = Status(iota)
|
||||||
StatusEOF
|
StatusEOF
|
||||||
StatusNoSuchFile
|
StatusNoSuchFile
|
||||||
@ -21,28 +21,28 @@ const (
|
|||||||
StatusConnectionLost
|
StatusConnectionLost
|
||||||
StatusOPUnsupported
|
StatusOPUnsupported
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-03#section-7
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-03.txt#section-7
|
||||||
StatusV4InvalidHandle
|
StatusV4InvalidHandle
|
||||||
StatusV4NoSuchPath
|
StatusV4NoSuchPath
|
||||||
StatusV4FileAlreadyExists
|
StatusV4FileAlreadyExists
|
||||||
StatusV4WriteProtect
|
StatusV4WriteProtect
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-7
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-04.txt#section-7
|
||||||
StatusV4NoMedia
|
StatusV4NoMedia
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-7
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-05.txt#section-7
|
||||||
StatusV5NoSpaceOnFilesystem
|
StatusV5NoSpaceOnFilesystem
|
||||||
StatusV5QuotaExceeded
|
StatusV5QuotaExceeded
|
||||||
StatusV5UnknownPrincipal
|
StatusV5UnknownPrincipal
|
||||||
StatusV5LockConflict
|
StatusV5LockConflict
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-06#section-8
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-06.txt#section-8
|
||||||
StatusV6DirNotEmpty
|
StatusV6DirNotEmpty
|
||||||
StatusV6NotADirectory
|
StatusV6NotADirectory
|
||||||
StatusV6InvalidFilename
|
StatusV6InvalidFilename
|
||||||
StatusV6LinkLoop
|
StatusV6LinkLoop
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-07#section-8
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-07.txt#section-8
|
||||||
StatusV6CannotDelete
|
StatusV6CannotDelete
|
||||||
StatusV6InvalidParameter
|
StatusV6InvalidParameter
|
||||||
StatusV6FileIsADirectory
|
StatusV6FileIsADirectory
|
||||||
@ -50,10 +50,10 @@ const (
|
|||||||
StatusV6ByteRangeLockRefused
|
StatusV6ByteRangeLockRefused
|
||||||
StatusV6DeletePending
|
StatusV6DeletePending
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-08#section-8.1
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-08.txt#section-8.1
|
||||||
StatusV6FileCorrupt
|
StatusV6FileCorrupt
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-10#section-9.1
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-10.txt#section-9.1
|
||||||
StatusV6OwnerInvalid
|
StatusV6OwnerInvalid
|
||||||
StatusV6GroupInvalid
|
StatusV6GroupInvalid
|
||||||
|
|
||||||
|
57
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/fxp.go
generated
vendored
57
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/fxp.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -9,7 +9,7 @@ type PacketType uint8
|
|||||||
|
|
||||||
// Request packet types.
|
// Request packet types.
|
||||||
const (
|
const (
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-3
|
||||||
PacketTypeInit = PacketType(iota + 1)
|
PacketTypeInit = PacketType(iota + 1)
|
||||||
PacketTypeVersion
|
PacketTypeVersion
|
||||||
PacketTypeOpen
|
PacketTypeOpen
|
||||||
@ -31,17 +31,17 @@ const (
|
|||||||
PacketTypeReadLink
|
PacketTypeReadLink
|
||||||
PacketTypeSymlink
|
PacketTypeSymlink
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-07#section-3.3
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-07.txt#section-3.3
|
||||||
PacketTypeV6Link
|
PacketTypeV6Link
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-08#section-3.3
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-08.txt#section-3.3
|
||||||
PacketTypeV6Block
|
PacketTypeV6Block
|
||||||
PacketTypeV6Unblock
|
PacketTypeV6Unblock
|
||||||
)
|
)
|
||||||
|
|
||||||
// Response packet types.
|
// Response packet types.
|
||||||
const (
|
const (
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-3
|
||||||
PacketTypeStatus = PacketType(iota + 101)
|
PacketTypeStatus = PacketType(iota + 101)
|
||||||
PacketTypeHandle
|
PacketTypeHandle
|
||||||
PacketTypeData
|
PacketTypeData
|
||||||
@ -51,7 +51,7 @@ const (
|
|||||||
|
|
||||||
// Extended packet types.
|
// Extended packet types.
|
||||||
const (
|
const (
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-3
|
||||||
PacketTypeExtended = PacketType(iota + 200)
|
PacketTypeExtended = PacketType(iota + 200)
|
||||||
PacketTypeExtendedReply
|
PacketTypeExtendedReply
|
||||||
)
|
)
|
||||||
@ -122,3 +122,48 @@ func (f PacketType) String() string {
|
|||||||
return fmt.Sprintf("SSH_FXP_UNKNOWN(%d)", f)
|
return fmt.Sprintf("SSH_FXP_UNKNOWN(%d)", f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newPacketFromType(typ PacketType) (Packet, error) {
|
||||||
|
switch typ {
|
||||||
|
case PacketTypeOpen:
|
||||||
|
return new(OpenPacket), nil
|
||||||
|
case PacketTypeClose:
|
||||||
|
return new(ClosePacket), nil
|
||||||
|
case PacketTypeRead:
|
||||||
|
return new(ReadPacket), nil
|
||||||
|
case PacketTypeWrite:
|
||||||
|
return new(WritePacket), nil
|
||||||
|
case PacketTypeLStat:
|
||||||
|
return new(LStatPacket), nil
|
||||||
|
case PacketTypeFStat:
|
||||||
|
return new(FStatPacket), nil
|
||||||
|
case PacketTypeSetstat:
|
||||||
|
return new(SetstatPacket), nil
|
||||||
|
case PacketTypeFSetstat:
|
||||||
|
return new(FSetstatPacket), nil
|
||||||
|
case PacketTypeOpenDir:
|
||||||
|
return new(OpenDirPacket), nil
|
||||||
|
case PacketTypeReadDir:
|
||||||
|
return new(ReadDirPacket), nil
|
||||||
|
case PacketTypeRemove:
|
||||||
|
return new(RemovePacket), nil
|
||||||
|
case PacketTypeMkdir:
|
||||||
|
return new(MkdirPacket), nil
|
||||||
|
case PacketTypeRmdir:
|
||||||
|
return new(RmdirPacket), nil
|
||||||
|
case PacketTypeRealPath:
|
||||||
|
return new(RealPathPacket), nil
|
||||||
|
case PacketTypeStat:
|
||||||
|
return new(StatPacket), nil
|
||||||
|
case PacketTypeRename:
|
||||||
|
return new(RenamePacket), nil
|
||||||
|
case PacketTypeReadLink:
|
||||||
|
return new(ReadLinkPacket), nil
|
||||||
|
case PacketTypeSymlink:
|
||||||
|
return new(SymlinkPacket), nil
|
||||||
|
case PacketTypeExtended:
|
||||||
|
return new(ExtendedPacket), nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unexpected request packet type: %v", typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
67
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/handle_packets.go
generated
vendored
67
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/handle_packets.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
// ClosePacket defines the SSH_FXP_CLOSE packet.
|
// ClosePacket defines the SSH_FXP_CLOSE packet.
|
||||||
type ClosePacket struct {
|
type ClosePacket struct {
|
||||||
@ -27,18 +27,18 @@ func (p *ClosePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []b
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *ClosePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *ClosePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
*p = ClosePacket{
|
||||||
return err
|
Handle: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadPacket defines the SSH_FXP_READ packet.
|
// ReadPacket defines the SSH_FXP_READ packet.
|
||||||
type ReadPacket struct {
|
type ReadPacket struct {
|
||||||
Handle string
|
Handle string
|
||||||
Offset uint64
|
Offset uint64
|
||||||
Len uint32
|
Length uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||||
@ -58,7 +58,7 @@ func (p *ReadPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []by
|
|||||||
buf.StartPacket(PacketTypeRead, reqid)
|
buf.StartPacket(PacketTypeRead, reqid)
|
||||||
buf.AppendString(p.Handle)
|
buf.AppendString(p.Handle)
|
||||||
buf.AppendUint64(p.Offset)
|
buf.AppendUint64(p.Offset)
|
||||||
buf.AppendUint32(p.Len)
|
buf.AppendUint32(p.Length)
|
||||||
|
|
||||||
return buf.Packet(payload)
|
return buf.Packet(payload)
|
||||||
}
|
}
|
||||||
@ -66,19 +66,13 @@ func (p *ReadPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []by
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *ReadPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *ReadPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
*p = ReadPacket{
|
||||||
return err
|
Handle: buf.ConsumeString(),
|
||||||
|
Offset: buf.ConsumeUint64(),
|
||||||
|
Length: buf.ConsumeUint32(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Offset, err = buf.ConsumeUint64(); err != nil {
|
return buf.Err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Len, err = buf.ConsumeUint32(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WritePacket defines the SSH_FXP_WRITE packet.
|
// WritePacket defines the SSH_FXP_WRITE packet.
|
||||||
@ -121,26 +115,13 @@ func (p *WritePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []b
|
|||||||
//
|
//
|
||||||
// This means this _does not_ alias any of the data buffer that is passed in.
|
// This means this _does not_ alias any of the data buffer that is passed in.
|
||||||
func (p *WritePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *WritePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
*p = WritePacket{
|
||||||
return err
|
Handle: buf.ConsumeString(),
|
||||||
|
Offset: buf.ConsumeUint64(),
|
||||||
|
Data: buf.ConsumeByteSliceCopy(p.Data),
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.Offset, err = buf.ConsumeUint64(); err != nil {
|
return buf.Err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := buf.ConsumeByteSlice()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p.Data) < len(data) {
|
|
||||||
p.Data = make([]byte, len(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
n := copy(p.Data, data)
|
|
||||||
p.Data = p.Data[:n]
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FStatPacket defines the SSH_FXP_FSTAT packet.
|
// FStatPacket defines the SSH_FXP_FSTAT packet.
|
||||||
@ -170,11 +151,11 @@ func (p *FStatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []b
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *FStatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *FStatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
*p = FStatPacket{
|
||||||
return err
|
Handle: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// FSetstatPacket defines the SSH_FXP_FSETSTAT packet.
|
// FSetstatPacket defines the SSH_FXP_FSETSTAT packet.
|
||||||
@ -207,8 +188,8 @@ func (p *FSetstatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *FSetstatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *FSetstatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
*p = FSetstatPacket{
|
||||||
return err
|
Handle: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.Attrs.UnmarshalFrom(buf)
|
return p.Attrs.UnmarshalFrom(buf)
|
||||||
@ -241,9 +222,9 @@ func (p *ReadDirPacket) MarshalPacket(reqid uint32, b []byte) (header, payload [
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *ReadDirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *ReadDirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
*p = ReadDirPacket{
|
||||||
return err
|
Handle: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
12
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/init_packets.go
generated
vendored
12
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/init_packets.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
// InitPacket defines the SSH_FXP_INIT packet.
|
// InitPacket defines the SSH_FXP_INIT packet.
|
||||||
type InitPacket struct {
|
type InitPacket struct {
|
||||||
@ -33,8 +33,8 @@ func (p *InitPacket) MarshalBinary() ([]byte, error) {
|
|||||||
func (p *InitPacket) UnmarshalBinary(data []byte) (err error) {
|
func (p *InitPacket) UnmarshalBinary(data []byte) (err error) {
|
||||||
buf := NewBuffer(data)
|
buf := NewBuffer(data)
|
||||||
|
|
||||||
if p.Version, err = buf.ConsumeUint32(); err != nil {
|
*p = InitPacket{
|
||||||
return err
|
Version: buf.ConsumeUint32(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for buf.Len() > 0 {
|
for buf.Len() > 0 {
|
||||||
@ -46,7 +46,7 @@ func (p *InitPacket) UnmarshalBinary(data []byte) (err error) {
|
|||||||
p.Extensions = append(p.Extensions, &ext)
|
p.Extensions = append(p.Extensions, &ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// VersionPacket defines the SSH_FXP_VERSION packet.
|
// VersionPacket defines the SSH_FXP_VERSION packet.
|
||||||
@ -82,8 +82,8 @@ func (p *VersionPacket) MarshalBinary() ([]byte, error) {
|
|||||||
func (p *VersionPacket) UnmarshalBinary(data []byte) (err error) {
|
func (p *VersionPacket) UnmarshalBinary(data []byte) (err error) {
|
||||||
buf := NewBuffer(data)
|
buf := NewBuffer(data)
|
||||||
|
|
||||||
if p.Version, err = buf.ConsumeUint32(); err != nil {
|
*p = VersionPacket{
|
||||||
return err
|
Version: buf.ConsumeUint32(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for buf.Len() > 0 {
|
for buf.Len() > 0 {
|
||||||
|
17
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/open_packets.go
generated
vendored
17
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/open_packets.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
// SSH_FXF_* flags.
|
// SSH_FXF_* flags.
|
||||||
const (
|
const (
|
||||||
@ -43,12 +43,9 @@ func (p *OpenPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []by
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *OpenPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *OpenPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Filename, err = buf.ConsumeString(); err != nil {
|
*p = OpenPacket{
|
||||||
return err
|
Filename: buf.ConsumeString(),
|
||||||
}
|
PFlags: buf.ConsumeUint32(),
|
||||||
|
|
||||||
if p.PFlags, err = buf.ConsumeUint32(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.Attrs.UnmarshalFrom(buf)
|
return p.Attrs.UnmarshalFrom(buf)
|
||||||
@ -81,9 +78,9 @@ func (p *OpenDirPacket) MarshalPacket(reqid uint32, b []byte) (header, payload [
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *OpenDirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *OpenDirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
*p = OpenDirPacket{
|
||||||
return err
|
Path: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
84
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/packets.go
generated
vendored
84
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/packets.go
generated
vendored
@ -1,59 +1,13 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// smallBufferSize is an initial allocation minimal capacity.
|
// smallBufferSize is an initial allocation minimal capacity.
|
||||||
const smallBufferSize = 64
|
const smallBufferSize = 64
|
||||||
|
|
||||||
func newPacketFromType(typ PacketType) (Packet, error) {
|
|
||||||
switch typ {
|
|
||||||
case PacketTypeOpen:
|
|
||||||
return new(OpenPacket), nil
|
|
||||||
case PacketTypeClose:
|
|
||||||
return new(ClosePacket), nil
|
|
||||||
case PacketTypeRead:
|
|
||||||
return new(ReadPacket), nil
|
|
||||||
case PacketTypeWrite:
|
|
||||||
return new(WritePacket), nil
|
|
||||||
case PacketTypeLStat:
|
|
||||||
return new(LStatPacket), nil
|
|
||||||
case PacketTypeFStat:
|
|
||||||
return new(FStatPacket), nil
|
|
||||||
case PacketTypeSetstat:
|
|
||||||
return new(SetstatPacket), nil
|
|
||||||
case PacketTypeFSetstat:
|
|
||||||
return new(FSetstatPacket), nil
|
|
||||||
case PacketTypeOpenDir:
|
|
||||||
return new(OpenDirPacket), nil
|
|
||||||
case PacketTypeReadDir:
|
|
||||||
return new(ReadDirPacket), nil
|
|
||||||
case PacketTypeRemove:
|
|
||||||
return new(RemovePacket), nil
|
|
||||||
case PacketTypeMkdir:
|
|
||||||
return new(MkdirPacket), nil
|
|
||||||
case PacketTypeRmdir:
|
|
||||||
return new(RmdirPacket), nil
|
|
||||||
case PacketTypeRealPath:
|
|
||||||
return new(RealPathPacket), nil
|
|
||||||
case PacketTypeStat:
|
|
||||||
return new(StatPacket), nil
|
|
||||||
case PacketTypeRename:
|
|
||||||
return new(RenamePacket), nil
|
|
||||||
case PacketTypeReadLink:
|
|
||||||
return new(ReadLinkPacket), nil
|
|
||||||
case PacketTypeSymlink:
|
|
||||||
return new(SymlinkPacket), nil
|
|
||||||
case PacketTypeExtended:
|
|
||||||
return new(ExtendedPacket), nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unexpected request packet type: %v", typ)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RawPacket implements the general packet format from draft-ietf-secsh-filexfer-02
|
// RawPacket implements the general packet format from draft-ietf-secsh-filexfer-02
|
||||||
//
|
//
|
||||||
// RawPacket is intended for use in clients receiving responses,
|
// RawPacket is intended for use in clients receiving responses,
|
||||||
@ -63,7 +17,7 @@ func newPacketFromType(typ PacketType) (Packet, error) {
|
|||||||
// For servers expecting to receive arbitrary request packet types,
|
// For servers expecting to receive arbitrary request packet types,
|
||||||
// use RequestPacket.
|
// use RequestPacket.
|
||||||
//
|
//
|
||||||
// Defined in https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
// Defined in https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-3
|
||||||
type RawPacket struct {
|
type RawPacket struct {
|
||||||
PacketType PacketType
|
PacketType PacketType
|
||||||
RequestID uint32
|
RequestID uint32
|
||||||
@ -110,19 +64,14 @@ func (p *RawPacket) MarshalBinary() ([]byte, error) {
|
|||||||
// The Data field will alias the passed in Buffer,
|
// The Data field will alias the passed in Buffer,
|
||||||
// so the buffer passed in should not be reused before RawPacket.Reset().
|
// so the buffer passed in should not be reused before RawPacket.Reset().
|
||||||
func (p *RawPacket) UnmarshalFrom(buf *Buffer) error {
|
func (p *RawPacket) UnmarshalFrom(buf *Buffer) error {
|
||||||
typ, err := buf.ConsumeUint8()
|
*p = RawPacket{
|
||||||
if err != nil {
|
PacketType: PacketType(buf.ConsumeUint8()),
|
||||||
return err
|
RequestID: buf.ConsumeUint32(),
|
||||||
}
|
|
||||||
|
|
||||||
p.PacketType = PacketType(typ)
|
|
||||||
|
|
||||||
if p.RequestID, err = buf.ConsumeUint32(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Data = *buf
|
p.Data = *buf
|
||||||
return nil
|
|
||||||
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalBinary decodes a full raw packet out of the given data.
|
// UnmarshalBinary decodes a full raw packet out of the given data.
|
||||||
@ -225,7 +174,7 @@ func (p *RawPacket) ReadFrom(r io.Reader, b []byte, maxPacketLength uint32) erro
|
|||||||
// where automatic unmarshaling of the packet body does not make sense,
|
// where automatic unmarshaling of the packet body does not make sense,
|
||||||
// use RawPacket.
|
// use RawPacket.
|
||||||
//
|
//
|
||||||
// Defined in https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
// Defined in https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-3
|
||||||
type RequestPacket struct {
|
type RequestPacket struct {
|
||||||
RequestID uint32
|
RequestID uint32
|
||||||
|
|
||||||
@ -268,18 +217,19 @@ func (p *RequestPacket) MarshalBinary() ([]byte, error) {
|
|||||||
// The Request field may alias the passed in Buffer, (e.g. SSH_FXP_WRITE),
|
// The Request field may alias the passed in Buffer, (e.g. SSH_FXP_WRITE),
|
||||||
// so the buffer passed in should not be reused before RequestPacket.Reset().
|
// so the buffer passed in should not be reused before RequestPacket.Reset().
|
||||||
func (p *RequestPacket) UnmarshalFrom(buf *Buffer) error {
|
func (p *RequestPacket) UnmarshalFrom(buf *Buffer) error {
|
||||||
typ, err := buf.ConsumeUint8()
|
typ := PacketType(buf.ConsumeUint8())
|
||||||
|
if buf.Err != nil {
|
||||||
|
return buf.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := newPacketFromType(typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Request, err = newPacketFromType(PacketType(typ))
|
*p = RequestPacket{
|
||||||
if err != nil {
|
RequestID: buf.ConsumeUint32(),
|
||||||
return err
|
Request: req,
|
||||||
}
|
|
||||||
|
|
||||||
if p.RequestID, err = buf.ConsumeUint32(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.Request.UnmarshalPacketBody(buf)
|
return p.Request.UnmarshalPacketBody(buf)
|
||||||
|
72
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/path_packets.go
generated
vendored
72
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/path_packets.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
// LStatPacket defines the SSH_FXP_LSTAT packet.
|
// LStatPacket defines the SSH_FXP_LSTAT packet.
|
||||||
type LStatPacket struct {
|
type LStatPacket struct {
|
||||||
@ -27,11 +27,11 @@ func (p *LStatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []b
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *LStatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *LStatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
*p = LStatPacket{
|
||||||
return err
|
Path: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetstatPacket defines the SSH_FXP_SETSTAT packet.
|
// SetstatPacket defines the SSH_FXP_SETSTAT packet.
|
||||||
@ -64,8 +64,8 @@ func (p *SetstatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload [
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *SetstatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *SetstatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
*p = SetstatPacket{
|
||||||
return err
|
Path: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.Attrs.UnmarshalFrom(buf)
|
return p.Attrs.UnmarshalFrom(buf)
|
||||||
@ -98,11 +98,11 @@ func (p *RemovePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *RemovePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *RemovePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
*p = RemovePacket{
|
||||||
return err
|
Path: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// MkdirPacket defines the SSH_FXP_MKDIR packet.
|
// MkdirPacket defines the SSH_FXP_MKDIR packet.
|
||||||
@ -135,8 +135,8 @@ func (p *MkdirPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []b
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *MkdirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *MkdirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
*p = MkdirPacket{
|
||||||
return err
|
Path: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.Attrs.UnmarshalFrom(buf)
|
return p.Attrs.UnmarshalFrom(buf)
|
||||||
@ -169,11 +169,11 @@ func (p *RmdirPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []b
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *RmdirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *RmdirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
*p = RmdirPacket{
|
||||||
return err
|
Path: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RealPathPacket defines the SSH_FXP_REALPATH packet.
|
// RealPathPacket defines the SSH_FXP_REALPATH packet.
|
||||||
@ -203,11 +203,11 @@ func (p *RealPathPacket) MarshalPacket(reqid uint32, b []byte) (header, payload
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *RealPathPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *RealPathPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
*p = RealPathPacket{
|
||||||
return err
|
Path: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatPacket defines the SSH_FXP_STAT packet.
|
// StatPacket defines the SSH_FXP_STAT packet.
|
||||||
@ -237,11 +237,11 @@ func (p *StatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []by
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *StatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *StatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
*p = StatPacket{
|
||||||
return err
|
Path: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenamePacket defines the SSH_FXP_RENAME packet.
|
// RenamePacket defines the SSH_FXP_RENAME packet.
|
||||||
@ -274,15 +274,12 @@ func (p *RenamePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *RenamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *RenamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.OldPath, err = buf.ConsumeString(); err != nil {
|
*p = RenamePacket{
|
||||||
return err
|
OldPath: buf.ConsumeString(),
|
||||||
|
NewPath: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.NewPath, err = buf.ConsumeString(); err != nil {
|
return buf.Err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadLinkPacket defines the SSH_FXP_READLINK packet.
|
// ReadLinkPacket defines the SSH_FXP_READLINK packet.
|
||||||
@ -312,18 +309,18 @@ func (p *ReadLinkPacket) MarshalPacket(reqid uint32, b []byte) (header, payload
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *ReadLinkPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *ReadLinkPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
*p = ReadLinkPacket{
|
||||||
return err
|
Path: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SymlinkPacket defines the SSH_FXP_SYMLINK packet.
|
// SymlinkPacket defines the SSH_FXP_SYMLINK packet.
|
||||||
//
|
//
|
||||||
// The order of the arguments to the SSH_FXP_SYMLINK method was inadvertently reversed.
|
// The order of the arguments to the SSH_FXP_SYMLINK method was inadvertently reversed.
|
||||||
// Unfortunately, the reversal was not noticed until the server was widely deployed.
|
// Unfortunately, the reversal was not noticed until the server was widely deployed.
|
||||||
// Covered in Section 3.1 of https://github.com/openssh/openssh-portable/blob/master/PROTOCOL
|
// Covered in Section 4.1 of https://github.com/openssh/openssh-portable/blob/master/PROTOCOL
|
||||||
type SymlinkPacket struct {
|
type SymlinkPacket struct {
|
||||||
LinkPath string
|
LinkPath string
|
||||||
TargetPath string
|
TargetPath string
|
||||||
@ -355,14 +352,11 @@ func (p *SymlinkPacket) MarshalPacket(reqid uint32, b []byte) (header, payload [
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *SymlinkPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *SymlinkPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
// Arguments were inadvertently reversed.
|
*p = SymlinkPacket{
|
||||||
if p.TargetPath, err = buf.ConsumeString(); err != nil {
|
// Arguments were inadvertently reversed.
|
||||||
return err
|
TargetPath: buf.ConsumeString(),
|
||||||
|
LinkPath: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.LinkPath, err = buf.ConsumeString(); err != nil {
|
return buf.Err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/permissions.go
generated
vendored
2
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/permissions.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
// FileMode represents a file’s mode and permission bits.
|
// FileMode represents a file’s mode and permission bits.
|
||||||
// The bits are defined according to POSIX standards,
|
// The bits are defined according to POSIX standards,
|
||||||
|
57
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/response_packets.go
generated
vendored
57
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/response_packets.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
package filexfer
|
package sshfx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
// StatusPacket defines the SSH_FXP_STATUS packet.
|
// StatusPacket defines the SSH_FXP_STATUS packet.
|
||||||
//
|
//
|
||||||
// Specified in https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7
|
// Specified in https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-7
|
||||||
type StatusPacket struct {
|
type StatusPacket struct {
|
||||||
StatusCode Status
|
StatusCode Status
|
||||||
ErrorMessage string
|
ErrorMessage string
|
||||||
@ -19,7 +19,7 @@ func (p *StatusPacket) Error() string {
|
|||||||
return "sftp: " + p.StatusCode.String()
|
return "sftp: " + p.StatusCode.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("sftp: %q (%s)", p.ErrorMessage, p.StatusCode)
|
return fmt.Sprintf("sftp: %s: %q", p.StatusCode, p.ErrorMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is returns true if target is a StatusPacket with the same StatusCode,
|
// Is returns true if target is a StatusPacket with the same StatusCode,
|
||||||
@ -57,21 +57,13 @@ func (p *StatusPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *StatusPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *StatusPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
statusCode, err := buf.ConsumeUint32()
|
*p = StatusPacket{
|
||||||
if err != nil {
|
StatusCode: Status(buf.ConsumeUint32()),
|
||||||
return err
|
ErrorMessage: buf.ConsumeString(),
|
||||||
}
|
LanguageTag: buf.ConsumeString(),
|
||||||
p.StatusCode = Status(statusCode)
|
|
||||||
|
|
||||||
if p.ErrorMessage, err = buf.ConsumeString(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.LanguageTag, err = buf.ConsumeString(); err != nil {
|
return buf.Err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandlePacket defines the SSH_FXP_HANDLE packet.
|
// HandlePacket defines the SSH_FXP_HANDLE packet.
|
||||||
@ -101,11 +93,11 @@ func (p *HandlePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *HandlePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *HandlePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
*p = HandlePacket{
|
||||||
return err
|
Handle: buf.ConsumeString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataPacket defines the SSH_FXP_DATA packet.
|
// DataPacket defines the SSH_FXP_DATA packet.
|
||||||
@ -143,18 +135,11 @@ func (p *DataPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []by
|
|||||||
//
|
//
|
||||||
// This means this _does not_ alias any of the data buffer that is passed in.
|
// This means this _does not_ alias any of the data buffer that is passed in.
|
||||||
func (p *DataPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *DataPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
data, err := buf.ConsumeByteSlice()
|
*p = DataPacket{
|
||||||
if err != nil {
|
Data: buf.ConsumeByteSliceCopy(p.Data),
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p.Data) < len(data) {
|
return buf.Err
|
||||||
p.Data = make([]byte, len(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
n := copy(p.Data, data)
|
|
||||||
p.Data = p.Data[:n]
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamePacket defines the SSH_FXP_NAME packet.
|
// NamePacket defines the SSH_FXP_NAME packet.
|
||||||
@ -193,14 +178,16 @@ func (p *NamePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []by
|
|||||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||||
// It is assumed that the uint32(request-id) has already been consumed.
|
// It is assumed that the uint32(request-id) has already been consumed.
|
||||||
func (p *NamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
func (p *NamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||||
count, err := buf.ConsumeUint32()
|
count := buf.ConsumeCount()
|
||||||
if err != nil {
|
if buf.Err != nil {
|
||||||
return err
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Entries = make([]*NameEntry, 0, count)
|
*p = NamePacket{
|
||||||
|
Entries: make([]*NameEntry, 0, count),
|
||||||
|
}
|
||||||
|
|
||||||
for i := uint32(0); i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
var e NameEntry
|
var e NameEntry
|
||||||
if err := e.UnmarshalFrom(buf); err != nil {
|
if err := e.UnmarshalFrom(buf); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -209,7 +196,7 @@ func (p *NamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
|||||||
p.Entries = append(p.Entries, &e)
|
p.Entries = append(p.Entries, &e)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// AttrsPacket defines the SSH_FXP_ATTRS packet.
|
// AttrsPacket defines the SSH_FXP_ATTRS packet.
|
||||||
|
7
vendor/github.com/pkg/sftp/ls_formatting.go
generated
vendored
7
vendor/github.com/pkg/sftp/ls_formatting.go
generated
vendored
@ -60,6 +60,13 @@ func runLs(idLookup NameLookupFileLister, dirent os.FileInfo) string {
|
|||||||
uid = lsFormatID(sys.UID)
|
uid = lsFormatID(sys.UID)
|
||||||
gid = lsFormatID(sys.GID)
|
gid = lsFormatID(sys.GID)
|
||||||
default:
|
default:
|
||||||
|
if fiExt, ok := dirent.(FileInfoUidGid); ok {
|
||||||
|
uid = lsFormatID(fiExt.Uid())
|
||||||
|
gid = lsFormatID(fiExt.Gid())
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
numLinks, uid, gid = lsLinksUIDGID(dirent)
|
numLinks, uid, gid = lsLinksUIDGID(dirent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
vendor/github.com/pkg/sftp/ls_plan9.go
generated
vendored
1
vendor/github.com/pkg/sftp/ls_plan9.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build plan9
|
||||||
// +build plan9
|
// +build plan9
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
1
vendor/github.com/pkg/sftp/ls_stub.go
generated
vendored
1
vendor/github.com/pkg/sftp/ls_stub.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows || android
|
||||||
// +build windows android
|
// +build windows android
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
1
vendor/github.com/pkg/sftp/ls_unix.go
generated
vendored
1
vendor/github.com/pkg/sftp/ls_unix.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build aix || darwin || dragonfly || freebsd || (!android && linux) || netbsd || openbsd || solaris || js
|
||||||
// +build aix darwin dragonfly freebsd !android,linux netbsd openbsd solaris js
|
// +build aix darwin dragonfly freebsd !android,linux netbsd openbsd solaris js
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
4
vendor/github.com/pkg/sftp/packet-manager.go
generated
vendored
4
vendor/github.com/pkg/sftp/packet-manager.go
generated
vendored
@ -40,7 +40,7 @@ func newPktMgr(sender packetSender) *packetManager {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
//// packet ordering
|
// // packet ordering
|
||||||
func (s *packetManager) newOrderID() uint32 {
|
func (s *packetManager) newOrderID() uint32 {
|
||||||
s.packetCount++
|
s.packetCount++
|
||||||
return s.packetCount
|
return s.packetCount
|
||||||
@ -89,7 +89,7 @@ func (o orderedPackets) Sort() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//// packet registry
|
// // packet registry
|
||||||
// register incoming packets to be handled
|
// register incoming packets to be handled
|
||||||
func (s *packetManager) incomingPacket(pkt orderedRequest) {
|
func (s *packetManager) incomingPacket(pkt orderedRequest) {
|
||||||
s.working.Add(1)
|
s.working.Add(1)
|
||||||
|
2
vendor/github.com/pkg/sftp/packet-typing.go
generated
vendored
2
vendor/github.com/pkg/sftp/packet-typing.go
generated
vendored
@ -31,7 +31,7 @@ type notReadOnly interface {
|
|||||||
notReadOnly()
|
notReadOnly()
|
||||||
}
|
}
|
||||||
|
|
||||||
//// define types by adding methods
|
// // define types by adding methods
|
||||||
// hasPath
|
// hasPath
|
||||||
func (p *sshFxpLstatPacket) getPath() string { return p.Path }
|
func (p *sshFxpLstatPacket) getPath() string { return p.Path }
|
||||||
func (p *sshFxpStatPacket) getPath() string { return p.Path }
|
func (p *sshFxpStatPacket) getPath() string { return p.Path }
|
||||||
|
25
vendor/github.com/pkg/sftp/packet.go
generated
vendored
25
vendor/github.com/pkg/sftp/packet.go
generated
vendored
@ -71,6 +71,15 @@ func marshalFileInfo(b []byte, fi os.FileInfo) []byte {
|
|||||||
b = marshalUint32(b, fileStat.Mtime)
|
b = marshalUint32(b, fileStat.Mtime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if flags&sshFileXferAttrExtended != 0 {
|
||||||
|
b = marshalUint32(b, uint32(len(fileStat.Extended)))
|
||||||
|
|
||||||
|
for _, attr := range fileStat.Extended {
|
||||||
|
b = marshalString(b, attr.ExtType)
|
||||||
|
b = marshalString(b, attr.ExtData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,6 +290,11 @@ func recvPacket(r io.Reader, alloc *allocator, orderID uint32) (uint8, []byte, e
|
|||||||
b = make([]byte, length)
|
b = make([]byte, length)
|
||||||
}
|
}
|
||||||
if _, err := io.ReadFull(r, b[:length]); err != nil {
|
if _, err := io.ReadFull(r, b[:length]); err != nil {
|
||||||
|
// ReadFull only returns EOF if it has read no bytes.
|
||||||
|
// In this case, that means a partial packet, and thus unexpected.
|
||||||
|
if err == io.EOF {
|
||||||
|
err = io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
debug("recv packet %d bytes: err %v", length, err)
|
debug("recv packet %d bytes: err %v", length, err)
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
@ -522,7 +536,12 @@ func (p *sshFxpRmdirPacket) UnmarshalBinary(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type sshFxpSymlinkPacket struct {
|
type sshFxpSymlinkPacket struct {
|
||||||
ID uint32
|
ID uint32
|
||||||
|
|
||||||
|
// The order of the arguments to the SSH_FXP_SYMLINK method was inadvertently reversed.
|
||||||
|
// Unfortunately, the reversal was not noticed until the server was widely deployed.
|
||||||
|
// Covered in Section 4.1 of https://github.com/openssh/openssh-portable/blob/master/PROTOCOL
|
||||||
|
|
||||||
Targetpath string
|
Targetpath string
|
||||||
Linkpath string
|
Linkpath string
|
||||||
}
|
}
|
||||||
@ -1242,7 +1261,7 @@ func (p *sshFxpExtendedPacketPosixRename) UnmarshalBinary(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *sshFxpExtendedPacketPosixRename) respond(s *Server) responsePacket {
|
func (p *sshFxpExtendedPacketPosixRename) respond(s *Server) responsePacket {
|
||||||
err := os.Rename(toLocalPath(p.Oldpath), toLocalPath(p.Newpath))
|
err := os.Rename(s.toLocalPath(p.Oldpath), s.toLocalPath(p.Newpath))
|
||||||
return statusFromError(p.ID, err)
|
return statusFromError(p.ID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1271,6 +1290,6 @@ func (p *sshFxpExtendedPacketHardlink) UnmarshalBinary(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *sshFxpExtendedPacketHardlink) respond(s *Server) responsePacket {
|
func (p *sshFxpExtendedPacketHardlink) respond(s *Server) responsePacket {
|
||||||
err := os.Link(toLocalPath(p.Oldpath), toLocalPath(p.Newpath))
|
err := os.Link(s.toLocalPath(p.Oldpath), s.toLocalPath(p.Newpath))
|
||||||
return statusFromError(p.ID, err)
|
return statusFromError(p.ID, err)
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/pkg/sftp/release.go
generated
vendored
1
vendor/github.com/pkg/sftp/release.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !debug
|
||||||
// +build !debug
|
// +build !debug
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
41
vendor/github.com/pkg/sftp/request-example.go
generated
vendored
41
vendor/github.com/pkg/sftp/request-example.go
generated
vendored
@ -391,21 +391,6 @@ func (fs *root) Filelist(r *Request) (ListerAt, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return listerat{file}, nil
|
return listerat{file}, nil
|
||||||
|
|
||||||
case "Readlink":
|
|
||||||
symlink, err := fs.readlink(r.Filepath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SFTP-v2: The server will respond with a SSH_FXP_NAME packet containing only
|
|
||||||
// one name and a dummy attributes value.
|
|
||||||
return listerat{
|
|
||||||
&memFile{
|
|
||||||
name: symlink,
|
|
||||||
err: os.ErrNotExist, // prevent accidental use as a reader/writer.
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("unsupported")
|
return nil, errors.New("unsupported")
|
||||||
@ -434,7 +419,7 @@ func (fs *root) readdir(pathname string) ([]os.FileInfo, error) {
|
|||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *root) readlink(pathname string) (string, error) {
|
func (fs *root) Readlink(pathname string) (string, error) {
|
||||||
file, err := fs.lfetch(pathname)
|
file, err := fs.lfetch(pathname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -464,19 +449,10 @@ func (fs *root) Lstat(r *Request) (ListerAt, error) {
|
|||||||
return listerat{file}, nil
|
return listerat{file}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// implements RealpathFileLister interface
|
|
||||||
func (fs *root) Realpath(p string) string {
|
|
||||||
if fs.startDirectory == "" || fs.startDirectory == "/" {
|
|
||||||
return cleanPath(p)
|
|
||||||
}
|
|
||||||
return cleanPathWithBase(fs.startDirectory, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// In memory file-system-y thing that the Hanlders live on
|
// In memory file-system-y thing that the Hanlders live on
|
||||||
type root struct {
|
type root struct {
|
||||||
rootFile *memFile
|
rootFile *memFile
|
||||||
mockErr error
|
mockErr error
|
||||||
startDirectory string
|
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
files map[string]*memFile
|
files map[string]*memFile
|
||||||
@ -534,8 +510,8 @@ func (fs *root) exists(path string) bool {
|
|||||||
return err != os.ErrNotExist
|
return err != os.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *root) fetch(path string) (*memFile, error) {
|
func (fs *root) fetch(pathname string) (*memFile, error) {
|
||||||
file, err := fs.lfetch(path)
|
file, err := fs.lfetch(pathname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -546,7 +522,12 @@ func (fs *root) fetch(path string) (*memFile, error) {
|
|||||||
return nil, errTooManySymlinks
|
return nil, errTooManySymlinks
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err = fs.lfetch(file.symlink)
|
linkTarget := file.symlink
|
||||||
|
if !path.IsAbs(linkTarget) {
|
||||||
|
linkTarget = path.Join(path.Dir(file.name), linkTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err = fs.lfetch(linkTarget)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
48
vendor/github.com/pkg/sftp/request-interfaces.go
generated
vendored
48
vendor/github.com/pkg/sftp/request-interfaces.go
generated
vendored
@ -74,6 +74,11 @@ type StatVFSFileCmder interface {
|
|||||||
// FileLister should return an object that fulfils the ListerAt interface
|
// FileLister should return an object that fulfils the ListerAt interface
|
||||||
// Note in cases of an error, the error text will be sent to the client.
|
// Note in cases of an error, the error text will be sent to the client.
|
||||||
// Called for Methods: List, Stat, Readlink
|
// Called for Methods: List, Stat, Readlink
|
||||||
|
//
|
||||||
|
// Since Filelist returns an os.FileInfo, this can make it non-ideal for implementing Readlink.
|
||||||
|
// This is because the Name receiver method defined by that interface defines that it should only return the base name.
|
||||||
|
// However, Readlink is required to be capable of returning essentially any arbitrary valid path relative or absolute.
|
||||||
|
// In order to implement this more expressive requirement, implement [ReadlinkFileLister] which will then be used instead.
|
||||||
type FileLister interface {
|
type FileLister interface {
|
||||||
Filelist(*Request) (ListerAt, error)
|
Filelist(*Request) (ListerAt, error)
|
||||||
}
|
}
|
||||||
@ -87,12 +92,33 @@ type LstatFileLister interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RealPathFileLister is a FileLister that implements the Realpath method.
|
// RealPathFileLister is a FileLister that implements the Realpath method.
|
||||||
// We use "/" as start directory for relative paths, implementing this
|
// The built-in RealPath implementation does not resolve symbolic links.
|
||||||
// interface you can customize the start directory.
|
// By implementing this interface you can customize the returned path
|
||||||
|
// and, for example, resolve symbolinc links if needed for your use case.
|
||||||
// You have to return an absolute POSIX path.
|
// You have to return an absolute POSIX path.
|
||||||
//
|
//
|
||||||
// Deprecated: if you want to set a start directory use WithStartDirectory RequestServerOption instead.
|
// Up to v1.13.5 the signature for the RealPath method was:
|
||||||
|
//
|
||||||
|
// # RealPath(string) string
|
||||||
|
//
|
||||||
|
// we have added a legacyRealPathFileLister that implements the old method
|
||||||
|
// to ensure that your code does not break.
|
||||||
|
// You should use the new method signature to avoid future issues
|
||||||
type RealPathFileLister interface {
|
type RealPathFileLister interface {
|
||||||
|
FileLister
|
||||||
|
RealPath(string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadlinkFileLister is a FileLister that implements the Readlink method.
|
||||||
|
// By implementing the Readlink method, it is possible to return any arbitrary valid path relative or absolute.
|
||||||
|
// This allows giving a better response than via the default FileLister (which is limited to os.FileInfo, whose Name method should only return the base name of a file)
|
||||||
|
type ReadlinkFileLister interface {
|
||||||
|
FileLister
|
||||||
|
Readlink(string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This interface is here for backward compatibility only
|
||||||
|
type legacyRealPathFileLister interface {
|
||||||
FileLister
|
FileLister
|
||||||
RealPath(string) string
|
RealPath(string) string
|
||||||
}
|
}
|
||||||
@ -105,11 +131,19 @@ type NameLookupFileLister interface {
|
|||||||
LookupGroupName(string) string
|
LookupGroupName(string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListerAt does for file lists what io.ReaderAt does for files.
|
// ListerAt does for file lists what io.ReaderAt does for files, i.e. a []os.FileInfo buffer is passed to the ListAt function
|
||||||
// ListAt should return the number of entries copied and an io.EOF
|
// and the entries that are populated in the buffer will be passed to the client.
|
||||||
// error if at end of list. This is testable by comparing how many you
|
//
|
||||||
// copied to how many could be copied (eg. n < len(ls) below).
|
// ListAt should return the number of entries copied and an io.EOF error if at end of list.
|
||||||
|
// This is testable by comparing how many you copied to how many could be copied (eg. n < len(ls) below).
|
||||||
// The copy() builtin is best for the copying.
|
// The copy() builtin is best for the copying.
|
||||||
|
//
|
||||||
|
// Uid and gid information will on unix systems be retrieved from [os.FileInfo.Sys]
|
||||||
|
// if this function returns a [syscall.Stat_t] when called on a populated entry.
|
||||||
|
// Alternatively, if the entry implements [FileInfoUidGid], it will be used for uid and gid information.
|
||||||
|
//
|
||||||
|
// If a populated entry implements [FileInfoExtendedData], extended attributes will also be returned to the client.
|
||||||
|
//
|
||||||
// Note in cases of an error, the error text will be sent to the client.
|
// Note in cases of an error, the error text will be sent to the client.
|
||||||
type ListerAt interface {
|
type ListerAt interface {
|
||||||
ListAt([]os.FileInfo, int64) (int, error)
|
ListAt([]os.FileInfo, int64) (int, error)
|
||||||
|
20
vendor/github.com/pkg/sftp/request-plan9.go
generated
vendored
20
vendor/github.com/pkg/sftp/request-plan9.go
generated
vendored
@ -1,10 +1,9 @@
|
|||||||
|
//go:build plan9
|
||||||
// +build plan9
|
// +build plan9
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,20 +14,3 @@ func fakeFileInfoSys() interface{} {
|
|||||||
func testOsSys(sys interface{}) error {
|
func testOsSys(sys interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toLocalPath(p string) string {
|
|
||||||
lp := filepath.FromSlash(p)
|
|
||||||
|
|
||||||
if path.IsAbs(p) {
|
|
||||||
tmp := lp[1:]
|
|
||||||
|
|
||||||
if filepath.IsAbs(tmp) {
|
|
||||||
// If the FromSlash without any starting slashes is absolute,
|
|
||||||
// then we have a filepath encoded with a prefix '/'.
|
|
||||||
// e.g. "/#s/boot" to "#s/boot"
|
|
||||||
return tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lp
|
|
||||||
}
|
|
||||||
|
2
vendor/github.com/pkg/sftp/request-readme.md
generated
vendored
2
vendor/github.com/pkg/sftp/request-readme.md
generated
vendored
@ -28,7 +28,7 @@ then sends to the client.
|
|||||||
Handler for "Put" method and returns an io.Writer for the file which the server
|
Handler for "Put" method and returns an io.Writer for the file which the server
|
||||||
then writes the uploaded file to. The file opening "pflags" are currently
|
then writes the uploaded file to. The file opening "pflags" are currently
|
||||||
preserved in the Request.Flags field as a 32bit bitmask value. See the [SFTP
|
preserved in the Request.Flags field as a 32bit bitmask value. See the [SFTP
|
||||||
spec](https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.3) for
|
spec](https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-6.3) for
|
||||||
details.
|
details.
|
||||||
|
|
||||||
### Filecmd(*Request) error
|
### Filecmd(*Request) error
|
||||||
|
17
vendor/github.com/pkg/sftp/request-server.go
generated
vendored
17
vendor/github.com/pkg/sftp/request-server.go
generated
vendored
@ -219,12 +219,21 @@ func (rs *RequestServer) packetWorker(ctx context.Context, pktChan chan orderedR
|
|||||||
rpkt = statusFromError(pkt.ID, rs.closeRequest(handle))
|
rpkt = statusFromError(pkt.ID, rs.closeRequest(handle))
|
||||||
case *sshFxpRealpathPacket:
|
case *sshFxpRealpathPacket:
|
||||||
var realPath string
|
var realPath string
|
||||||
if realPather, ok := rs.Handlers.FileList.(RealPathFileLister); ok {
|
var err error
|
||||||
realPath = realPather.RealPath(pkt.getPath())
|
|
||||||
} else {
|
switch pather := rs.Handlers.FileList.(type) {
|
||||||
|
case RealPathFileLister:
|
||||||
|
realPath, err = pather.RealPath(pkt.getPath())
|
||||||
|
case legacyRealPathFileLister:
|
||||||
|
realPath = pather.RealPath(pkt.getPath())
|
||||||
|
default:
|
||||||
realPath = cleanPathWithBase(rs.startDirectory, pkt.getPath())
|
realPath = cleanPathWithBase(rs.startDirectory, pkt.getPath())
|
||||||
}
|
}
|
||||||
rpkt = cleanPacketPath(pkt, realPath)
|
if err != nil {
|
||||||
|
rpkt = statusFromError(pkt.ID, err)
|
||||||
|
} else {
|
||||||
|
rpkt = cleanPacketPath(pkt, realPath)
|
||||||
|
}
|
||||||
case *sshFxpOpendirPacket:
|
case *sshFxpOpendirPacket:
|
||||||
request := requestFromPacket(ctx, pkt, rs.startDirectory)
|
request := requestFromPacket(ctx, pkt, rs.startDirectory)
|
||||||
handle := rs.nextRequest(request)
|
handle := rs.nextRequest(request)
|
||||||
|
5
vendor/github.com/pkg/sftp/request-unix.go
generated
vendored
5
vendor/github.com/pkg/sftp/request-unix.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !windows && !plan9
|
||||||
// +build !windows,!plan9
|
// +build !windows,!plan9
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
@ -21,7 +22,3 @@ func testOsSys(sys interface{}) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toLocalPath(p string) string {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
25
vendor/github.com/pkg/sftp/request.go
generated
vendored
25
vendor/github.com/pkg/sftp/request.go
generated
vendored
@ -187,6 +187,7 @@ func requestFromPacket(ctx context.Context, pkt hasPath, baseDir string) *Reques
|
|||||||
// NOTE: given a POSIX compliant signature: symlink(target, linkpath string)
|
// NOTE: given a POSIX compliant signature: symlink(target, linkpath string)
|
||||||
// this makes Request.Target the linkpath, and Request.Filepath the target.
|
// this makes Request.Target the linkpath, and Request.Filepath the target.
|
||||||
request.Target = cleanPathWithBase(baseDir, p.Linkpath)
|
request.Target = cleanPathWithBase(baseDir, p.Linkpath)
|
||||||
|
request.Filepath = p.Targetpath
|
||||||
case *sshFxpExtendedPacketHardlink:
|
case *sshFxpExtendedPacketHardlink:
|
||||||
request.Target = cleanPathWithBase(baseDir, p.Newpath)
|
request.Target = cleanPathWithBase(baseDir, p.Newpath)
|
||||||
}
|
}
|
||||||
@ -294,7 +295,12 @@ func (r *Request) call(handlers Handlers, pkt requestPacket, alloc *allocator, o
|
|||||||
return filecmd(handlers.FileCmd, r, pkt)
|
return filecmd(handlers.FileCmd, r, pkt)
|
||||||
case "List":
|
case "List":
|
||||||
return filelist(handlers.FileList, r, pkt)
|
return filelist(handlers.FileList, r, pkt)
|
||||||
case "Stat", "Lstat", "Readlink":
|
case "Stat", "Lstat":
|
||||||
|
return filestat(handlers.FileList, r, pkt)
|
||||||
|
case "Readlink":
|
||||||
|
if readlinkFileLister, ok := handlers.FileList.(ReadlinkFileLister); ok {
|
||||||
|
return readlink(readlinkFileLister, r, pkt)
|
||||||
|
}
|
||||||
return filestat(handlers.FileList, r, pkt)
|
return filestat(handlers.FileList, r, pkt)
|
||||||
default:
|
default:
|
||||||
return statusFromError(pkt.id(), fmt.Errorf("unexpected method: %s", r.Method))
|
return statusFromError(pkt.id(), fmt.Errorf("unexpected method: %s", r.Method))
|
||||||
@ -598,6 +604,23 @@ func filestat(h FileLister, r *Request, pkt requestPacket) responsePacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readlink(readlinkFileLister ReadlinkFileLister, r *Request, pkt requestPacket) responsePacket {
|
||||||
|
resolved, err := readlinkFileLister.Readlink(r.Filepath)
|
||||||
|
if err != nil {
|
||||||
|
return statusFromError(pkt.id(), err)
|
||||||
|
}
|
||||||
|
return &sshFxpNamePacket{
|
||||||
|
ID: pkt.id(),
|
||||||
|
NameAttrs: []*sshFxpNameAttr{
|
||||||
|
{
|
||||||
|
Name: resolved,
|
||||||
|
LongName: resolved,
|
||||||
|
Attrs: emptyFileStat,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// init attributes of request object from packet data
|
// init attributes of request object from packet data
|
||||||
func requestMethod(p requestPacket) (method string) {
|
func requestMethod(p requestPacket) (method string) {
|
||||||
switch p.(type) {
|
switch p.(type) {
|
||||||
|
31
vendor/github.com/pkg/sftp/request_windows.go
generated
vendored
31
vendor/github.com/pkg/sftp/request_windows.go
generated
vendored
@ -1,8 +1,6 @@
|
|||||||
package sftp
|
package sftp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,32 +11,3 @@ func fakeFileInfoSys() interface{} {
|
|||||||
func testOsSys(sys interface{}) error {
|
func testOsSys(sys interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toLocalPath(p string) string {
|
|
||||||
lp := filepath.FromSlash(p)
|
|
||||||
|
|
||||||
if path.IsAbs(p) {
|
|
||||||
tmp := lp
|
|
||||||
for len(tmp) > 0 && tmp[0] == '\\' {
|
|
||||||
tmp = tmp[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if filepath.IsAbs(tmp) {
|
|
||||||
// If the FromSlash without any starting slashes is absolute,
|
|
||||||
// then we have a filepath encoded with a prefix '/'.
|
|
||||||
// e.g. "/C:/Windows" to "C:\\Windows"
|
|
||||||
return tmp
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp += "\\"
|
|
||||||
|
|
||||||
if filepath.IsAbs(tmp) {
|
|
||||||
// If the FromSlash without any starting slashes but with extra end slash is absolute,
|
|
||||||
// then we have a filepath encoded with a prefix '/' and a dropped '/' at the end.
|
|
||||||
// e.g. "/C:" to "C:\\"
|
|
||||||
return tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lp
|
|
||||||
}
|
|
||||||
|
62
vendor/github.com/pkg/sftp/server.go
generated
vendored
62
vendor/github.com/pkg/sftp/server.go
generated
vendored
@ -24,7 +24,7 @@ const (
|
|||||||
// Server is an SSH File Transfer Protocol (sftp) server.
|
// Server is an SSH File Transfer Protocol (sftp) server.
|
||||||
// This is intended to provide the sftp subsystem to an ssh server daemon.
|
// This is intended to provide the sftp subsystem to an ssh server daemon.
|
||||||
// This implementation currently supports most of sftp server protocol version 3,
|
// This implementation currently supports most of sftp server protocol version 3,
|
||||||
// as specified at http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
|
// as specified at https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
|
||||||
type Server struct {
|
type Server struct {
|
||||||
*serverConn
|
*serverConn
|
||||||
debugStream io.Writer
|
debugStream io.Writer
|
||||||
@ -33,6 +33,7 @@ type Server struct {
|
|||||||
openFiles map[string]*os.File
|
openFiles map[string]*os.File
|
||||||
openFilesLock sync.RWMutex
|
openFilesLock sync.RWMutex
|
||||||
handleCount int
|
handleCount int
|
||||||
|
workDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (svr *Server) nextHandle(f *os.File) string {
|
func (svr *Server) nextHandle(f *os.File) string {
|
||||||
@ -128,6 +129,16 @@ func WithAllocator() ServerOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithServerWorkingDirectory sets a working directory to use as base
|
||||||
|
// for relative paths.
|
||||||
|
// If unset the default is current working directory (os.Getwd).
|
||||||
|
func WithServerWorkingDirectory(workDir string) ServerOption {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.workDir = cleanPath(workDir)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type rxPacket struct {
|
type rxPacket struct {
|
||||||
pktType fxp
|
pktType fxp
|
||||||
pktBytes []byte
|
pktBytes []byte
|
||||||
@ -174,7 +185,7 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||||||
}
|
}
|
||||||
case *sshFxpStatPacket:
|
case *sshFxpStatPacket:
|
||||||
// stat the requested file
|
// stat the requested file
|
||||||
info, err := os.Stat(toLocalPath(p.Path))
|
info, err := os.Stat(s.toLocalPath(p.Path))
|
||||||
rpkt = &sshFxpStatResponse{
|
rpkt = &sshFxpStatResponse{
|
||||||
ID: p.ID,
|
ID: p.ID,
|
||||||
info: info,
|
info: info,
|
||||||
@ -184,7 +195,7 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||||||
}
|
}
|
||||||
case *sshFxpLstatPacket:
|
case *sshFxpLstatPacket:
|
||||||
// stat the requested file
|
// stat the requested file
|
||||||
info, err := os.Lstat(toLocalPath(p.Path))
|
info, err := os.Lstat(s.toLocalPath(p.Path))
|
||||||
rpkt = &sshFxpStatResponse{
|
rpkt = &sshFxpStatResponse{
|
||||||
ID: p.ID,
|
ID: p.ID,
|
||||||
info: info,
|
info: info,
|
||||||
@ -208,24 +219,24 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||||||
}
|
}
|
||||||
case *sshFxpMkdirPacket:
|
case *sshFxpMkdirPacket:
|
||||||
// TODO FIXME: ignore flags field
|
// TODO FIXME: ignore flags field
|
||||||
err := os.Mkdir(toLocalPath(p.Path), 0755)
|
err := os.Mkdir(s.toLocalPath(p.Path), 0o755)
|
||||||
rpkt = statusFromError(p.ID, err)
|
rpkt = statusFromError(p.ID, err)
|
||||||
case *sshFxpRmdirPacket:
|
case *sshFxpRmdirPacket:
|
||||||
err := os.Remove(toLocalPath(p.Path))
|
err := os.Remove(s.toLocalPath(p.Path))
|
||||||
rpkt = statusFromError(p.ID, err)
|
rpkt = statusFromError(p.ID, err)
|
||||||
case *sshFxpRemovePacket:
|
case *sshFxpRemovePacket:
|
||||||
err := os.Remove(toLocalPath(p.Filename))
|
err := os.Remove(s.toLocalPath(p.Filename))
|
||||||
rpkt = statusFromError(p.ID, err)
|
rpkt = statusFromError(p.ID, err)
|
||||||
case *sshFxpRenamePacket:
|
case *sshFxpRenamePacket:
|
||||||
err := os.Rename(toLocalPath(p.Oldpath), toLocalPath(p.Newpath))
|
err := os.Rename(s.toLocalPath(p.Oldpath), s.toLocalPath(p.Newpath))
|
||||||
rpkt = statusFromError(p.ID, err)
|
rpkt = statusFromError(p.ID, err)
|
||||||
case *sshFxpSymlinkPacket:
|
case *sshFxpSymlinkPacket:
|
||||||
err := os.Symlink(toLocalPath(p.Targetpath), toLocalPath(p.Linkpath))
|
err := os.Symlink(s.toLocalPath(p.Targetpath), s.toLocalPath(p.Linkpath))
|
||||||
rpkt = statusFromError(p.ID, err)
|
rpkt = statusFromError(p.ID, err)
|
||||||
case *sshFxpClosePacket:
|
case *sshFxpClosePacket:
|
||||||
rpkt = statusFromError(p.ID, s.closeHandle(p.Handle))
|
rpkt = statusFromError(p.ID, s.closeHandle(p.Handle))
|
||||||
case *sshFxpReadlinkPacket:
|
case *sshFxpReadlinkPacket:
|
||||||
f, err := os.Readlink(toLocalPath(p.Path))
|
f, err := os.Readlink(s.toLocalPath(p.Path))
|
||||||
rpkt = &sshFxpNamePacket{
|
rpkt = &sshFxpNamePacket{
|
||||||
ID: p.ID,
|
ID: p.ID,
|
||||||
NameAttrs: []*sshFxpNameAttr{
|
NameAttrs: []*sshFxpNameAttr{
|
||||||
@ -240,7 +251,7 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||||||
rpkt = statusFromError(p.ID, err)
|
rpkt = statusFromError(p.ID, err)
|
||||||
}
|
}
|
||||||
case *sshFxpRealpathPacket:
|
case *sshFxpRealpathPacket:
|
||||||
f, err := filepath.Abs(toLocalPath(p.Path))
|
f, err := filepath.Abs(s.toLocalPath(p.Path))
|
||||||
f = cleanPath(f)
|
f = cleanPath(f)
|
||||||
rpkt = &sshFxpNamePacket{
|
rpkt = &sshFxpNamePacket{
|
||||||
ID: p.ID,
|
ID: p.ID,
|
||||||
@ -256,13 +267,14 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||||||
rpkt = statusFromError(p.ID, err)
|
rpkt = statusFromError(p.ID, err)
|
||||||
}
|
}
|
||||||
case *sshFxpOpendirPacket:
|
case *sshFxpOpendirPacket:
|
||||||
p.Path = toLocalPath(p.Path)
|
lp := s.toLocalPath(p.Path)
|
||||||
|
|
||||||
if stat, err := os.Stat(p.Path); err != nil {
|
if stat, err := os.Stat(lp); err != nil {
|
||||||
rpkt = statusFromError(p.ID, err)
|
rpkt = statusFromError(p.ID, err)
|
||||||
} else if !stat.IsDir() {
|
} else if !stat.IsDir() {
|
||||||
rpkt = statusFromError(p.ID, &os.PathError{
|
rpkt = statusFromError(p.ID, &os.PathError{
|
||||||
Path: p.Path, Err: syscall.ENOTDIR})
|
Path: lp, Err: syscall.ENOTDIR,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
rpkt = (&sshFxpOpenPacket{
|
rpkt = (&sshFxpOpenPacket{
|
||||||
ID: p.ID,
|
ID: p.ID,
|
||||||
@ -315,7 +327,7 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serve serves SFTP connections until the streams stop or the SFTP subsystem
|
// Serve serves SFTP connections until the streams stop or the SFTP subsystem
|
||||||
// is stopped.
|
// is stopped. It returns nil if the server exits cleanly.
|
||||||
func (svr *Server) Serve() error {
|
func (svr *Server) Serve() error {
|
||||||
defer func() {
|
defer func() {
|
||||||
if svr.pktMgr.alloc != nil {
|
if svr.pktMgr.alloc != nil {
|
||||||
@ -341,6 +353,10 @@ func (svr *Server) Serve() error {
|
|||||||
for {
|
for {
|
||||||
pktType, pktBytes, err = svr.serverConn.recvPacket(svr.pktMgr.getNextOrderID())
|
pktType, pktBytes, err = svr.serverConn.recvPacket(svr.pktMgr.getNextOrderID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Check whether the connection terminated cleanly in-between packets.
|
||||||
|
if err == io.EOF {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
// we don't care about releasing allocated pages here, the server will quit and the allocator freed
|
// we don't care about releasing allocated pages here, the server will quit and the allocator freed
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -446,7 +462,7 @@ func (p *sshFxpOpenPacket) respond(svr *Server) responsePacket {
|
|||||||
osFlags |= os.O_EXCL
|
osFlags |= os.O_EXCL
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.OpenFile(toLocalPath(p.Path), osFlags, 0644)
|
f, err := os.OpenFile(svr.toLocalPath(p.Path), osFlags, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return statusFromError(p.ID, err)
|
return statusFromError(p.ID, err)
|
||||||
}
|
}
|
||||||
@ -484,7 +500,7 @@ func (p *sshFxpSetstatPacket) respond(svr *Server) responsePacket {
|
|||||||
b := p.Attrs.([]byte)
|
b := p.Attrs.([]byte)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
p.Path = toLocalPath(p.Path)
|
p.Path = svr.toLocalPath(p.Path)
|
||||||
|
|
||||||
debug("setstat name \"%s\"", p.Path)
|
debug("setstat name \"%s\"", p.Path)
|
||||||
if (p.Flags & sshFileXferAttrSize) != 0 {
|
if (p.Flags & sshFileXferAttrSize) != 0 {
|
||||||
@ -603,13 +619,15 @@ func statusFromError(id uint32, err error) *sshFxpStatusPacket {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
switch e := err.(type) {
|
if errors.Is(err, io.EOF) {
|
||||||
case fxerr:
|
ret.StatusError.Code = sshFxEOF
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
var e fxerr
|
||||||
|
if errors.As(err, &e) {
|
||||||
ret.StatusError.Code = uint32(e)
|
ret.StatusError.Code = uint32(e)
|
||||||
default:
|
return ret
|
||||||
if e == io.EOF {
|
|
||||||
ret.StatusError.Code = sshFxEOF
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
27
vendor/github.com/pkg/sftp/server_plan9.go
generated
vendored
Normal file
27
vendor/github.com/pkg/sftp/server_plan9.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package sftp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) toLocalPath(p string) string {
|
||||||
|
if s.workDir != "" && !path.IsAbs(p) {
|
||||||
|
p = path.Join(s.workDir, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
lp := filepath.FromSlash(p)
|
||||||
|
|
||||||
|
if path.IsAbs(p) {
|
||||||
|
tmp := lp[1:]
|
||||||
|
|
||||||
|
if filepath.IsAbs(tmp) {
|
||||||
|
// If the FromSlash without any starting slashes is absolute,
|
||||||
|
// then we have a filepath encoded with a prefix '/'.
|
||||||
|
// e.g. "/#s/boot" to "#s/boot"
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lp
|
||||||
|
}
|
1
vendor/github.com/pkg/sftp/server_statvfs_impl.go
generated
vendored
1
vendor/github.com/pkg/sftp/server_statvfs_impl.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build darwin || linux
|
||||||
// +build darwin linux
|
// +build darwin linux
|
||||||
|
|
||||||
// fill in statvfs structure with OS specific values
|
// fill in statvfs structure with OS specific values
|
||||||
|
1
vendor/github.com/pkg/sftp/server_statvfs_linux.go
generated
vendored
1
vendor/github.com/pkg/sftp/server_statvfs_linux.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
1
vendor/github.com/pkg/sftp/server_statvfs_stubs.go
generated
vendored
1
vendor/github.com/pkg/sftp/server_statvfs_stubs.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !darwin && !linux && !plan9
|
||||||
// +build !darwin,!linux,!plan9
|
// +build !darwin,!linux,!plan9
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
16
vendor/github.com/pkg/sftp/server_unix.go
generated
vendored
Normal file
16
vendor/github.com/pkg/sftp/server_unix.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//go:build !windows && !plan9
|
||||||
|
// +build !windows,!plan9
|
||||||
|
|
||||||
|
package sftp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) toLocalPath(p string) string {
|
||||||
|
if s.workDir != "" && !path.IsAbs(p) {
|
||||||
|
p = path.Join(s.workDir, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
39
vendor/github.com/pkg/sftp/server_windows.go
generated
vendored
Normal file
39
vendor/github.com/pkg/sftp/server_windows.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package sftp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) toLocalPath(p string) string {
|
||||||
|
if s.workDir != "" && !path.IsAbs(p) {
|
||||||
|
p = path.Join(s.workDir, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
lp := filepath.FromSlash(p)
|
||||||
|
|
||||||
|
if path.IsAbs(p) {
|
||||||
|
tmp := lp
|
||||||
|
for len(tmp) > 0 && tmp[0] == '\\' {
|
||||||
|
tmp = tmp[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if filepath.IsAbs(tmp) {
|
||||||
|
// If the FromSlash without any starting slashes is absolute,
|
||||||
|
// then we have a filepath encoded with a prefix '/'.
|
||||||
|
// e.g. "/C:/Windows" to "C:\\Windows"
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp += "\\"
|
||||||
|
|
||||||
|
if filepath.IsAbs(tmp) {
|
||||||
|
// If the FromSlash without any starting slashes but with extra end slash is absolute,
|
||||||
|
// then we have a filepath encoded with a prefix '/' and a dropped '/' at the end.
|
||||||
|
// e.g. "/C:" to "C:\\"
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lp
|
||||||
|
}
|
2
vendor/github.com/pkg/sftp/sftp.go
generated
vendored
2
vendor/github.com/pkg/sftp/sftp.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// Package sftp implements the SSH File Transfer Protocol as described in
|
// Package sftp implements the SSH File Transfer Protocol as described in
|
||||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
|
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
|
||||||
package sftp
|
package sftp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
1
vendor/github.com/pkg/sftp/syscall_fixed.go
generated
vendored
1
vendor/github.com/pkg/sftp/syscall_fixed.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build plan9 || windows || (js && wasm)
|
||||||
// +build plan9 windows js,wasm
|
// +build plan9 windows js,wasm
|
||||||
|
|
||||||
// Go defines S_IFMT on windows, plan9 and js/wasm as 0x1f000 instead of
|
// Go defines S_IFMT on windows, plan9 and js/wasm as 0x1f000 instead of
|
||||||
|
4
vendor/github.com/pkg/sftp/syscall_good.go
generated
vendored
4
vendor/github.com/pkg/sftp/syscall_good.go
generated
vendored
@ -1,4 +1,6 @@
|
|||||||
// +build !plan9,!windows
|
//go:build !plan9 && !windows && (!js || !wasm)
|
||||||
|
// +build !plan9
|
||||||
|
// +build !windows
|
||||||
// +build !js !wasm
|
// +build !js !wasm
|
||||||
|
|
||||||
package sftp
|
package sftp
|
||||||
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@ -156,7 +156,7 @@ github.com/containers/buildah/pkg/rusage
|
|||||||
github.com/containers/buildah/pkg/sshagent
|
github.com/containers/buildah/pkg/sshagent
|
||||||
github.com/containers/buildah/pkg/util
|
github.com/containers/buildah/pkg/util
|
||||||
github.com/containers/buildah/util
|
github.com/containers/buildah/util
|
||||||
# github.com/containers/common v0.55.1-0.20230811093040-524b4d5c12f9
|
# github.com/containers/common v0.55.1-0.20230814161508-b70b0c49600e
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/containers/common/libimage
|
github.com/containers/common/libimage
|
||||||
github.com/containers/common/libimage/define
|
github.com/containers/common/libimage/define
|
||||||
@ -852,7 +852,7 @@ github.com/pelletier/go-toml/v2/unstable
|
|||||||
# github.com/pkg/errors v0.9.1
|
# github.com/pkg/errors v0.9.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/pkg/errors
|
github.com/pkg/errors
|
||||||
# github.com/pkg/sftp v1.13.5
|
# github.com/pkg/sftp v1.13.6
|
||||||
## explicit; go 1.15
|
## explicit; go 1.15
|
||||||
github.com/pkg/sftp
|
github.com/pkg/sftp
|
||||||
github.com/pkg/sftp/internal/encoding/ssh/filexfer
|
github.com/pkg/sftp/internal/encoding/ssh/filexfer
|
||||||
|
Reference in New Issue
Block a user