small fixes and dependency updates
This commit is contained in:
parent
e95910d920
commit
96405e2521
238 changed files with 3599 additions and 3467 deletions
3
vendor/github.com/go-logr/logr/.golangci.yaml
generated
vendored
3
vendor/github.com/go-logr/logr/.golangci.yaml
generated
vendored
|
|
@ -6,7 +6,6 @@ linters:
|
|||
disable-all: true
|
||||
enable:
|
||||
- asciicheck
|
||||
- deadcode
|
||||
- errcheck
|
||||
- forcetypeassert
|
||||
- gocritic
|
||||
|
|
@ -18,10 +17,8 @@ linters:
|
|||
- misspell
|
||||
- revive
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- typecheck
|
||||
- unused
|
||||
- varcheck
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
|
|
|
|||
32
vendor/github.com/go-logr/logr/discard.go
generated
vendored
32
vendor/github.com/go-logr/logr/discard.go
generated
vendored
|
|
@ -20,35 +20,5 @@ package logr
|
|||
// used whenever the caller is not interested in the logs. Logger instances
|
||||
// produced by this function always compare as equal.
|
||||
func Discard() Logger {
|
||||
return Logger{
|
||||
level: 0,
|
||||
sink: discardLogSink{},
|
||||
}
|
||||
}
|
||||
|
||||
// discardLogSink is a LogSink that discards all messages.
|
||||
type discardLogSink struct{}
|
||||
|
||||
// Verify that it actually implements the interface
|
||||
var _ LogSink = discardLogSink{}
|
||||
|
||||
func (l discardLogSink) Init(RuntimeInfo) {
|
||||
}
|
||||
|
||||
func (l discardLogSink) Enabled(int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (l discardLogSink) Info(int, string, ...interface{}) {
|
||||
}
|
||||
|
||||
func (l discardLogSink) Error(error, string, ...interface{}) {
|
||||
}
|
||||
|
||||
func (l discardLogSink) WithValues(...interface{}) LogSink {
|
||||
return l
|
||||
}
|
||||
|
||||
func (l discardLogSink) WithName(string) LogSink {
|
||||
return l
|
||||
return New(nil)
|
||||
}
|
||||
|
|
|
|||
166
vendor/github.com/go-logr/logr/logr.go
generated
vendored
166
vendor/github.com/go-logr/logr/logr.go
generated
vendored
|
|
@ -21,7 +21,7 @@ limitations under the License.
|
|||
// to back that API. Packages in the Go ecosystem can depend on this package,
|
||||
// while callers can implement logging with whatever backend is appropriate.
|
||||
//
|
||||
// Usage
|
||||
// # Usage
|
||||
//
|
||||
// Logging is done using a Logger instance. Logger is a concrete type with
|
||||
// methods, which defers the actual logging to a LogSink interface. The main
|
||||
|
|
@ -30,16 +30,20 @@ limitations under the License.
|
|||
// "structured logging".
|
||||
//
|
||||
// With Go's standard log package, we might write:
|
||||
// log.Printf("setting target value %s", targetValue)
|
||||
//
|
||||
// log.Printf("setting target value %s", targetValue)
|
||||
//
|
||||
// With logr's structured logging, we'd write:
|
||||
// logger.Info("setting target", "value", targetValue)
|
||||
//
|
||||
// logger.Info("setting target", "value", targetValue)
|
||||
//
|
||||
// Errors are much the same. Instead of:
|
||||
// log.Printf("failed to open the pod bay door for user %s: %v", user, err)
|
||||
//
|
||||
// log.Printf("failed to open the pod bay door for user %s: %v", user, err)
|
||||
//
|
||||
// We'd write:
|
||||
// logger.Error(err, "failed to open the pod bay door", "user", user)
|
||||
//
|
||||
// logger.Error(err, "failed to open the pod bay door", "user", user)
|
||||
//
|
||||
// Info() and Error() are very similar, but they are separate methods so that
|
||||
// LogSink implementations can choose to do things like attach additional
|
||||
|
|
@ -47,7 +51,7 @@ limitations under the License.
|
|||
// always logged, regardless of the current verbosity. If there is no error
|
||||
// instance available, passing nil is valid.
|
||||
//
|
||||
// Verbosity
|
||||
// # Verbosity
|
||||
//
|
||||
// Often we want to log information only when the application in "verbose
|
||||
// mode". To write log lines that are more verbose, Logger has a V() method.
|
||||
|
|
@ -58,20 +62,22 @@ limitations under the License.
|
|||
// Error messages do not have a verbosity level and are always logged.
|
||||
//
|
||||
// Where we might have written:
|
||||
// if flVerbose >= 2 {
|
||||
// log.Printf("an unusual thing happened")
|
||||
// }
|
||||
//
|
||||
// if flVerbose >= 2 {
|
||||
// log.Printf("an unusual thing happened")
|
||||
// }
|
||||
//
|
||||
// We can write:
|
||||
// logger.V(2).Info("an unusual thing happened")
|
||||
//
|
||||
// Logger Names
|
||||
// logger.V(2).Info("an unusual thing happened")
|
||||
//
|
||||
// # Logger Names
|
||||
//
|
||||
// Logger instances can have name strings so that all messages logged through
|
||||
// that instance have additional context. For example, you might want to add
|
||||
// a subsystem name:
|
||||
//
|
||||
// logger.WithName("compactor").Info("started", "time", time.Now())
|
||||
// logger.WithName("compactor").Info("started", "time", time.Now())
|
||||
//
|
||||
// The WithName() method returns a new Logger, which can be passed to
|
||||
// constructors or other functions for further use. Repeated use of WithName()
|
||||
|
|
@ -82,25 +88,27 @@ limitations under the License.
|
|||
// joining operation (e.g. whitespace, commas, periods, slashes, brackets,
|
||||
// quotes, etc).
|
||||
//
|
||||
// Saved Values
|
||||
// # Saved Values
|
||||
//
|
||||
// Logger instances can store any number of key/value pairs, which will be
|
||||
// logged alongside all messages logged through that instance. For example,
|
||||
// you might want to create a Logger instance per managed object:
|
||||
//
|
||||
// With the standard log package, we might write:
|
||||
// log.Printf("decided to set field foo to value %q for object %s/%s",
|
||||
// targetValue, object.Namespace, object.Name)
|
||||
//
|
||||
// log.Printf("decided to set field foo to value %q for object %s/%s",
|
||||
// targetValue, object.Namespace, object.Name)
|
||||
//
|
||||
// With logr we'd write:
|
||||
// // Elsewhere: set up the logger to log the object name.
|
||||
// obj.logger = mainLogger.WithValues(
|
||||
// "name", obj.name, "namespace", obj.namespace)
|
||||
//
|
||||
// // later on...
|
||||
// obj.logger.Info("setting foo", "value", targetValue)
|
||||
// // Elsewhere: set up the logger to log the object name.
|
||||
// obj.logger = mainLogger.WithValues(
|
||||
// "name", obj.name, "namespace", obj.namespace)
|
||||
//
|
||||
// Best Practices
|
||||
// // later on...
|
||||
// obj.logger.Info("setting foo", "value", targetValue)
|
||||
//
|
||||
// # Best Practices
|
||||
//
|
||||
// Logger has very few hard rules, with the goal that LogSink implementations
|
||||
// might have a lot of freedom to differentiate. There are, however, some
|
||||
|
|
@ -124,15 +132,15 @@ limitations under the License.
|
|||
// around. For cases where passing a logger is optional, a pointer to Logger
|
||||
// should be used.
|
||||
//
|
||||
// Key Naming Conventions
|
||||
// # Key Naming Conventions
|
||||
//
|
||||
// Keys are not strictly required to conform to any specification or regex, but
|
||||
// it is recommended that they:
|
||||
// * be human-readable and meaningful (not auto-generated or simple ordinals)
|
||||
// * be constant (not dependent on input data)
|
||||
// * contain only printable characters
|
||||
// * not contain whitespace or punctuation
|
||||
// * use lower case for simple keys and lowerCamelCase for more complex ones
|
||||
// - be human-readable and meaningful (not auto-generated or simple ordinals)
|
||||
// - be constant (not dependent on input data)
|
||||
// - contain only printable characters
|
||||
// - not contain whitespace or punctuation
|
||||
// - use lower case for simple keys and lowerCamelCase for more complex ones
|
||||
//
|
||||
// These guidelines help ensure that log data is processed properly regardless
|
||||
// of the log implementation. For example, log implementations will try to
|
||||
|
|
@ -141,51 +149,54 @@ limitations under the License.
|
|||
// While users are generally free to use key names of their choice, it's
|
||||
// generally best to avoid using the following keys, as they're frequently used
|
||||
// by implementations:
|
||||
// * "caller": the calling information (file/line) of a particular log line
|
||||
// * "error": the underlying error value in the `Error` method
|
||||
// * "level": the log level
|
||||
// * "logger": the name of the associated logger
|
||||
// * "msg": the log message
|
||||
// * "stacktrace": the stack trace associated with a particular log line or
|
||||
// error (often from the `Error` message)
|
||||
// * "ts": the timestamp for a log line
|
||||
// - "caller": the calling information (file/line) of a particular log line
|
||||
// - "error": the underlying error value in the `Error` method
|
||||
// - "level": the log level
|
||||
// - "logger": the name of the associated logger
|
||||
// - "msg": the log message
|
||||
// - "stacktrace": the stack trace associated with a particular log line or
|
||||
// error (often from the `Error` message)
|
||||
// - "ts": the timestamp for a log line
|
||||
//
|
||||
// Implementations are encouraged to make use of these keys to represent the
|
||||
// above concepts, when necessary (for example, in a pure-JSON output form, it
|
||||
// would be necessary to represent at least message and timestamp as ordinary
|
||||
// named values).
|
||||
//
|
||||
// Break Glass
|
||||
// # Break Glass
|
||||
//
|
||||
// Implementations may choose to give callers access to the underlying
|
||||
// logging implementation. The recommended pattern for this is:
|
||||
// // Underlier exposes access to the underlying logging implementation.
|
||||
// // Since callers only have a logr.Logger, they have to know which
|
||||
// // implementation is in use, so this interface is less of an abstraction
|
||||
// // and more of way to test type conversion.
|
||||
// type Underlier interface {
|
||||
// GetUnderlying() <underlying-type>
|
||||
// }
|
||||
//
|
||||
// // Underlier exposes access to the underlying logging implementation.
|
||||
// // Since callers only have a logr.Logger, they have to know which
|
||||
// // implementation is in use, so this interface is less of an abstraction
|
||||
// // and more of way to test type conversion.
|
||||
// type Underlier interface {
|
||||
// GetUnderlying() <underlying-type>
|
||||
// }
|
||||
//
|
||||
// Logger grants access to the sink to enable type assertions like this:
|
||||
// func DoSomethingWithImpl(log logr.Logger) {
|
||||
// if underlier, ok := log.GetSink()(impl.Underlier) {
|
||||
// implLogger := underlier.GetUnderlying()
|
||||
// ...
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func DoSomethingWithImpl(log logr.Logger) {
|
||||
// if underlier, ok := log.GetSink().(impl.Underlier); ok {
|
||||
// implLogger := underlier.GetUnderlying()
|
||||
// ...
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Custom `With*` functions can be implemented by copying the complete
|
||||
// Logger struct and replacing the sink in the copy:
|
||||
// // WithFooBar changes the foobar parameter in the log sink and returns a
|
||||
// // new logger with that modified sink. It does nothing for loggers where
|
||||
// // the sink doesn't support that parameter.
|
||||
// func WithFoobar(log logr.Logger, foobar int) logr.Logger {
|
||||
// if foobarLogSink, ok := log.GetSink()(FoobarSink); ok {
|
||||
// log = log.WithSink(foobarLogSink.WithFooBar(foobar))
|
||||
// }
|
||||
// return log
|
||||
// }
|
||||
//
|
||||
// // WithFooBar changes the foobar parameter in the log sink and returns a
|
||||
// // new logger with that modified sink. It does nothing for loggers where
|
||||
// // the sink doesn't support that parameter.
|
||||
// func WithFoobar(log logr.Logger, foobar int) logr.Logger {
|
||||
// if foobarLogSink, ok := log.GetSink().(FoobarSink); ok {
|
||||
// log = log.WithSink(foobarLogSink.WithFooBar(foobar))
|
||||
// }
|
||||
// return log
|
||||
// }
|
||||
//
|
||||
// Don't use New to construct a new Logger with a LogSink retrieved from an
|
||||
// existing Logger. Source code attribution might not work correctly and
|
||||
|
|
@ -201,11 +212,14 @@ import (
|
|||
)
|
||||
|
||||
// New returns a new Logger instance. This is primarily used by libraries
|
||||
// implementing LogSink, rather than end users.
|
||||
// implementing LogSink, rather than end users. Passing a nil sink will create
|
||||
// a Logger which discards all log lines.
|
||||
func New(sink LogSink) Logger {
|
||||
logger := Logger{}
|
||||
logger.setSink(sink)
|
||||
sink.Init(runtimeInfo)
|
||||
if sink != nil {
|
||||
sink.Init(runtimeInfo)
|
||||
}
|
||||
return logger
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +258,7 @@ type Logger struct {
|
|||
// Enabled tests whether this Logger is enabled. For example, commandline
|
||||
// flags might be used to set the logging verbosity and disable some info logs.
|
||||
func (l Logger) Enabled() bool {
|
||||
return l.sink.Enabled(l.level)
|
||||
return l.sink != nil && l.sink.Enabled(l.level)
|
||||
}
|
||||
|
||||
// Info logs a non-error message with the given key/value pairs as context.
|
||||
|
|
@ -254,6 +268,9 @@ func (l Logger) Enabled() bool {
|
|||
// information. The key/value pairs must alternate string keys and arbitrary
|
||||
// values.
|
||||
func (l Logger) Info(msg string, keysAndValues ...interface{}) {
|
||||
if l.sink == nil {
|
||||
return
|
||||
}
|
||||
if l.Enabled() {
|
||||
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
||||
withHelper.GetCallStackHelper()()
|
||||
|
|
@ -273,6 +290,9 @@ func (l Logger) Info(msg string, keysAndValues ...interface{}) {
|
|||
// triggered this log line, if present. The err parameter is optional
|
||||
// and nil may be passed instead of an error instance.
|
||||
func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||
if l.sink == nil {
|
||||
return
|
||||
}
|
||||
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
||||
withHelper.GetCallStackHelper()()
|
||||
}
|
||||
|
|
@ -284,6 +304,9 @@ func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
|
|||
// level means a log message is less important. Negative V-levels are treated
|
||||
// as 0.
|
||||
func (l Logger) V(level int) Logger {
|
||||
if l.sink == nil {
|
||||
return l
|
||||
}
|
||||
if level < 0 {
|
||||
level = 0
|
||||
}
|
||||
|
|
@ -294,6 +317,9 @@ func (l Logger) V(level int) Logger {
|
|||
// WithValues returns a new Logger instance with additional key/value pairs.
|
||||
// See Info for documentation on how key/value pairs work.
|
||||
func (l Logger) WithValues(keysAndValues ...interface{}) Logger {
|
||||
if l.sink == nil {
|
||||
return l
|
||||
}
|
||||
l.setSink(l.sink.WithValues(keysAndValues...))
|
||||
return l
|
||||
}
|
||||
|
|
@ -304,6 +330,9 @@ func (l Logger) WithValues(keysAndValues ...interface{}) Logger {
|
|||
// contain only letters, digits, and hyphens (see the package documentation for
|
||||
// more information).
|
||||
func (l Logger) WithName(name string) Logger {
|
||||
if l.sink == nil {
|
||||
return l
|
||||
}
|
||||
l.setSink(l.sink.WithName(name))
|
||||
return l
|
||||
}
|
||||
|
|
@ -324,6 +353,9 @@ func (l Logger) WithName(name string) Logger {
|
|||
// WithCallDepth(1) because it works with implementions that support the
|
||||
// CallDepthLogSink and/or CallStackHelperLogSink interfaces.
|
||||
func (l Logger) WithCallDepth(depth int) Logger {
|
||||
if l.sink == nil {
|
||||
return l
|
||||
}
|
||||
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
|
||||
l.setSink(withCallDepth.WithCallDepth(depth))
|
||||
}
|
||||
|
|
@ -345,6 +377,9 @@ func (l Logger) WithCallDepth(depth int) Logger {
|
|||
// implementation does not support either of these, the original Logger will be
|
||||
// returned.
|
||||
func (l Logger) WithCallStackHelper() (func(), Logger) {
|
||||
if l.sink == nil {
|
||||
return func() {}, l
|
||||
}
|
||||
var helper func()
|
||||
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
|
||||
l.setSink(withCallDepth.WithCallDepth(1))
|
||||
|
|
@ -357,6 +392,11 @@ func (l Logger) WithCallStackHelper() (func(), Logger) {
|
|||
return helper, l
|
||||
}
|
||||
|
||||
// IsZero returns true if this logger is an uninitialized zero value
|
||||
func (l Logger) IsZero() bool {
|
||||
return l.sink == nil
|
||||
}
|
||||
|
||||
// contextKey is how we find Loggers in a context.Context.
|
||||
type contextKey struct{}
|
||||
|
||||
|
|
@ -442,7 +482,7 @@ type LogSink interface {
|
|||
WithName(name string) LogSink
|
||||
}
|
||||
|
||||
// CallDepthLogSink represents a Logger that knows how to climb the call stack
|
||||
// CallDepthLogSink represents a LogSink that knows how to climb the call stack
|
||||
// to identify the original call site and can offset the depth by a specified
|
||||
// number of frames. This is useful for users who have helper functions
|
||||
// between the "real" call site and the actual calls to Logger methods.
|
||||
|
|
@ -467,7 +507,7 @@ type CallDepthLogSink interface {
|
|||
WithCallDepth(depth int) LogSink
|
||||
}
|
||||
|
||||
// CallStackHelperLogSink represents a Logger that knows how to climb
|
||||
// CallStackHelperLogSink represents a LogSink that knows how to climb
|
||||
// the call stack to identify the original call site and can skip
|
||||
// intermediate helper functions if they mark themselves as
|
||||
// helper. Go's testing package uses that approach.
|
||||
|
|
|
|||
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
|
||||
|
||||
// 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 (
|
||||
"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) {
|
||||
mtime := fi.ModTime().Unix()
|
||||
atime := mtime
|
||||
|
|
@ -86,5 +100,22 @@ func fileStatFromInfo(fi os.FileInfo) (uint32, *FileStat) {
|
|||
// os specific file stat decoding
|
||||
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
|
||||
}
|
||||
|
|
|
|||
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
|
||||
|
||||
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
|
||||
|
||||
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"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
|
|
@ -226,15 +227,22 @@ func NewClientPipe(rd io.Reader, wr io.WriteCloser, opts ...ClientOption) (*Clie
|
|||
|
||||
if err := sftp.sendInit(); err != nil {
|
||||
wr.Close()
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error sending init packet to server: %w", err)
|
||||
}
|
||||
|
||||
if err := sftp.recvVersion(); err != nil {
|
||||
wr.Close()
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error receiving version packet from server: %w", err)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
typ, data, err := c.recvPacket(0)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return fmt.Errorf("server unexpectedly closed connection: %w", io.ErrUnexpectedEOF)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if typ != sshFxpVersion {
|
||||
return &unexpectedPacketErr{sshFxpVersion, typ}
|
||||
}
|
||||
|
|
@ -277,6 +290,7 @@ func (c *Client) recvVersion() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if version != sftpProtocolVersion {
|
||||
return &unexpectedVersionErr{sftpProtocolVersion, version}
|
||||
}
|
||||
|
|
@ -910,6 +924,45 @@ func (c *Client) MkdirAll(path string) error {
|
|||
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.
|
||||
type File struct {
|
||||
c *Client
|
||||
|
|
@ -1660,7 +1713,7 @@ func (f *File) ReadFromWithConcurrency(r io.Reader, concurrency int) (read int64
|
|||
Handle: f.handle,
|
||||
Offset: uint64(off),
|
||||
Length: uint32(n),
|
||||
Data: b,
|
||||
Data: b[:n],
|
||||
})
|
||||
|
||||
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.
|
||||
// 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) {
|
||||
return recvPacket(c, c.alloc, orderID)
|
||||
}
|
||||
|
|
@ -61,14 +63,6 @@ func (c *clientConn) Close() error {
|
|||
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
|
||||
// appropriate channel.
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
const (
|
||||
|
|
@ -12,7 +12,7 @@ const (
|
|||
|
||||
// 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 {
|
||||
Flags uint32
|
||||
|
||||
|
|
@ -116,32 +116,32 @@ func (a *Attributes) Len() int {
|
|||
}
|
||||
|
||||
// MarshalInto marshals e onto the end of the given Buffer.
|
||||
func (a *Attributes) MarshalInto(b *Buffer) {
|
||||
b.AppendUint32(a.Flags)
|
||||
func (a *Attributes) MarshalInto(buf *Buffer) {
|
||||
buf.AppendUint32(a.Flags)
|
||||
|
||||
if a.Flags&AttrSize != 0 {
|
||||
b.AppendUint64(a.Size)
|
||||
buf.AppendUint64(a.Size)
|
||||
}
|
||||
|
||||
if a.Flags&AttrUIDGID != 0 {
|
||||
b.AppendUint32(a.UID)
|
||||
b.AppendUint32(a.GID)
|
||||
buf.AppendUint32(a.UID)
|
||||
buf.AppendUint32(a.GID)
|
||||
}
|
||||
|
||||
if a.Flags&AttrPermissions != 0 {
|
||||
b.AppendUint32(uint32(a.Permissions))
|
||||
buf.AppendUint32(uint32(a.Permissions))
|
||||
}
|
||||
|
||||
if a.Flags&AttrACModTime != 0 {
|
||||
b.AppendUint32(a.ATime)
|
||||
b.AppendUint32(a.MTime)
|
||||
buf.AppendUint32(a.ATime)
|
||||
buf.AppendUint32(a.MTime)
|
||||
}
|
||||
|
||||
if a.Flags&AttrExtended != 0 {
|
||||
b.AppendUint32(uint32(len(a.ExtendedAttributes)))
|
||||
buf.AppendUint32(uint32(len(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.
|
||||
//
|
||||
// NOTE: The values of fields not covered in the a.Flags are explicitly undefined.
|
||||
func (a *Attributes) UnmarshalFrom(b *Buffer) (err error) {
|
||||
flags, err := b.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (a *Attributes) UnmarshalFrom(buf *Buffer) (err error) {
|
||||
flags := buf.ConsumeUint32()
|
||||
|
||||
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.
|
||||
// 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.
|
||||
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
|
||||
|
||||
// Short-circuit dummy attributes.
|
||||
if a.Flags == 0 {
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
if a.Flags&AttrSize != 0 {
|
||||
if a.Size, err = b.ConsumeUint64(); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Size = buf.ConsumeUint64()
|
||||
}
|
||||
|
||||
if a.Flags&AttrUIDGID != 0 {
|
||||
if a.UID, err = b.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.GID, err = b.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
a.UID = buf.ConsumeUint32()
|
||||
a.GID = buf.ConsumeUint32()
|
||||
}
|
||||
|
||||
if a.Flags&AttrPermissions != 0 {
|
||||
m, err := b.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.Permissions = FileMode(m)
|
||||
a.Permissions = FileMode(buf.ConsumeUint32())
|
||||
}
|
||||
|
||||
if a.Flags&AttrACModTime != 0 {
|
||||
if a.ATime, err = b.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.MTime, err = b.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
a.ATime = buf.ConsumeUint32()
|
||||
a.MTime = buf.ConsumeUint32()
|
||||
}
|
||||
|
||||
if a.Flags&AttrExtended != 0 {
|
||||
count, err := b.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
count := buf.ConsumeCount()
|
||||
|
||||
a.ExtendedAttributes = make([]ExtendedAttribute, count)
|
||||
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.
|
||||
|
|
@ -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
|
||||
//
|
||||
// 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 string
|
||||
Data string
|
||||
|
|
@ -245,9 +222,9 @@ func (e *ExtendedAttribute) Len() int {
|
|||
}
|
||||
|
||||
// MarshalInto marshals e onto the end of the given Buffer.
|
||||
func (e *ExtendedAttribute) MarshalInto(b *Buffer) {
|
||||
b.AppendString(e.Type)
|
||||
b.AppendString(e.Data)
|
||||
func (e *ExtendedAttribute) MarshalInto(buf *Buffer) {
|
||||
buf.AppendString(e.Type)
|
||||
buf.AppendString(e.Data)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (e *ExtendedAttribute) UnmarshalFrom(b *Buffer) (err error) {
|
||||
if e.Type, err = b.ConsumeString(); err != nil {
|
||||
return err
|
||||
func (e *ExtendedAttribute) UnmarshalFrom(buf *Buffer) (err error) {
|
||||
*e = ExtendedAttribute{
|
||||
Type: buf.ConsumeString(),
|
||||
Data: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
if e.Data, err = b.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (e *NameEntry) MarshalInto(b *Buffer) {
|
||||
b.AppendString(e.Filename)
|
||||
b.AppendString(e.Longname)
|
||||
func (e *NameEntry) MarshalInto(buf *Buffer) {
|
||||
buf.AppendString(e.Filename)
|
||||
buf.AppendString(e.Longname)
|
||||
|
||||
e.Attrs.MarshalInto(b)
|
||||
e.Attrs.MarshalInto(buf)
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// NOTE: The values of fields not covered in the a.Flags are explicitly undefined.
|
||||
func (e *NameEntry) UnmarshalFrom(b *Buffer) (err error) {
|
||||
if e.Filename, err = b.ConsumeString(); err != nil {
|
||||
return err
|
||||
func (e *NameEntry) UnmarshalFrom(buf *Buffer) (err error) {
|
||||
*e = NameEntry{
|
||||
Filename: buf.ConsumeString(),
|
||||
Longname: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
if e.Longname, err = b.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.Attrs.UnmarshalFrom(b)
|
||||
return e.Attrs.UnmarshalFrom(buf)
|
||||
}
|
||||
|
||||
// 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 (
|
||||
"encoding/binary"
|
||||
|
|
@ -17,6 +17,7 @@ var (
|
|||
type Buffer struct {
|
||||
b []byte
|
||||
off int
|
||||
Err error
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (b *Buffer) Reset() {
|
||||
b.b = b.b[:0]
|
||||
b.off = 0
|
||||
*b = Buffer{
|
||||
b: b.b[:0],
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
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.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.
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint8() (uint8, error) {
|
||||
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint8() uint8 {
|
||||
if b.Err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
if b.Len() < 1 {
|
||||
return 0, ErrShortPacket
|
||||
b.off = len(b.b)
|
||||
b.Err = ErrShortPacket
|
||||
return 0
|
||||
}
|
||||
|
||||
var v uint8
|
||||
v, b.off = b.b[b.off], b.off+1
|
||||
return v, nil
|
||||
return v
|
||||
}
|
||||
|
||||
// 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.
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeBool() (bool, error) {
|
||||
v, err := b.ConsumeUint8()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return v != 0, nil
|
||||
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||
func (b *Buffer) ConsumeBool() bool {
|
||||
return b.ConsumeUint8() != 0
|
||||
}
|
||||
|
||||
// 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).
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint16() (uint16, error) {
|
||||
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint16() uint16 {
|
||||
if b.Err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
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:])
|
||||
b.off += 2
|
||||
return v, nil
|
||||
return v
|
||||
}
|
||||
|
||||
// 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).
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint32() (uint32, error) {
|
||||
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint32() uint32 {
|
||||
if b.Err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
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:])
|
||||
b.off += 4
|
||||
return v, nil
|
||||
return v
|
||||
}
|
||||
|
||||
// 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).
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint64() (uint64, error) {
|
||||
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint64() uint64 {
|
||||
if b.Err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
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:])
|
||||
b.off += 8
|
||||
return v, nil
|
||||
return v
|
||||
}
|
||||
|
||||
// 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.
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeInt64() (int64, error) {
|
||||
u, err := b.ConsumeUint64()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int64(u), err
|
||||
// If the buffer does not have enough data, it will set Err to ErrShortPacket.
|
||||
func (b *Buffer) ConsumeInt64() int64 {
|
||||
return int64(b.ConsumeUint64())
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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
|
||||
// (that is, only until the next call to Reset, PutLength, StartPacket, or UnmarshalBinary).
|
||||
//
|
||||
// In no case will any Consume calls return overlapping slice aliases,
|
||||
// and Append calls are guaranteed to not disturb this slice alias.
|
||||
func (b *Buffer) ConsumeByteSlice() ([]byte, error) {
|
||||
length, err := b.ConsumeUint32()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (b *Buffer) ConsumeByteSlice() []byte {
|
||||
length := int(b.ConsumeUint32())
|
||||
if b.Err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if b.Len() < int(length) {
|
||||
return nil, ErrShortPacket
|
||||
if b.Len() < length || length < 0 {
|
||||
b.off = len(b.b)
|
||||
b.Err = ErrShortPacket
|
||||
return nil
|
||||
}
|
||||
|
||||
v := b.b[b.off:]
|
||||
if len(v) > int(length) {
|
||||
if len(v) > length || cap(v) > length {
|
||||
v = v[:length: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.
|
||||
|
|
@ -245,17 +297,12 @@ func (b *Buffer) AppendByteSlice(v []byte) {
|
|||
|
||||
// ConsumeString consumes a single string of binary data 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 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.
|
||||
// All caveats on using arbitrary binary data in Go strings applies.
|
||||
func (b *Buffer) ConsumeString() (string, error) {
|
||||
v, err := b.ConsumeByteSlice()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(v), nil
|
||||
func (b *Buffer) ConsumeString() string {
|
||||
return string(b.ConsumeByteSlice())
|
||||
}
|
||||
|
||||
// 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 (
|
||||
"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.
|
||||
// Then the request-specific-data will be unmarshaled from the rest of the buffer.
|
||||
func (p *ExtendedPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.ExtendedRequest, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
p.ExtendedRequest = buf.ConsumeString()
|
||||
if buf.Err != nil {
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
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.
|
||||
// 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.
|
||||
func (e *ExtensionPair) UnmarshalFrom(buf *Buffer) (err error) {
|
||||
if e.Name, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*e = ExtensionPair{
|
||||
Name: buf.ConsumeString(),
|
||||
Data: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
if e.Data, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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 filexfer
|
||||
// Package sshfx implements the wire encoding for secsh-filexfer as described in https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
|
||||
package sshfx
|
||||
|
||||
// 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 (
|
||||
"fmt"
|
||||
|
|
@ -10,7 +10,7 @@ type Status uint32
|
|||
// Defines the various SSH_FX_* values.
|
||||
const (
|
||||
// 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)
|
||||
StatusEOF
|
||||
StatusNoSuchFile
|
||||
|
|
@ -21,28 +21,28 @@ const (
|
|||
StatusConnectionLost
|
||||
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
|
||||
StatusV4NoSuchPath
|
||||
StatusV4FileAlreadyExists
|
||||
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
|
||||
|
||||
// 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
|
||||
StatusV5QuotaExceeded
|
||||
StatusV5UnknownPrincipal
|
||||
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
|
||||
StatusV6NotADirectory
|
||||
StatusV6InvalidFilename
|
||||
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
|
||||
StatusV6InvalidParameter
|
||||
StatusV6FileIsADirectory
|
||||
|
|
@ -50,10 +50,10 @@ const (
|
|||
StatusV6ByteRangeLockRefused
|
||||
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
|
||||
|
||||
// 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
|
||||
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 (
|
||||
"fmt"
|
||||
|
|
@ -9,7 +9,7 @@ type PacketType uint8
|
|||
|
||||
// Request packet types.
|
||||
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)
|
||||
PacketTypeVersion
|
||||
PacketTypeOpen
|
||||
|
|
@ -31,17 +31,17 @@ const (
|
|||
PacketTypeReadLink
|
||||
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
|
||||
|
||||
// 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
|
||||
PacketTypeV6Unblock
|
||||
)
|
||||
|
||||
// Response packet types.
|
||||
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)
|
||||
PacketTypeHandle
|
||||
PacketTypeData
|
||||
|
|
@ -51,7 +51,7 @@ const (
|
|||
|
||||
// Extended packet types.
|
||||
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)
|
||||
PacketTypeExtendedReply
|
||||
)
|
||||
|
|
@ -122,3 +122,48 @@ func (f PacketType) String() string {
|
|||
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.
|
||||
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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *ClosePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = ClosePacket{
|
||||
Handle: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// ReadPacket defines the SSH_FXP_READ packet.
|
||||
type ReadPacket struct {
|
||||
Handle string
|
||||
Offset uint64
|
||||
Len uint32
|
||||
Length uint32
|
||||
}
|
||||
|
||||
// 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.AppendString(p.Handle)
|
||||
buf.AppendUint64(p.Offset)
|
||||
buf.AppendUint32(p.Len)
|
||||
buf.AppendUint32(p.Length)
|
||||
|
||||
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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *ReadPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = ReadPacket{
|
||||
Handle: buf.ConsumeString(),
|
||||
Offset: buf.ConsumeUint64(),
|
||||
Length: buf.ConsumeUint32(),
|
||||
}
|
||||
|
||||
if p.Offset, err = buf.ConsumeUint64(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Len, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (p *WritePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = WritePacket{
|
||||
Handle: buf.ConsumeString(),
|
||||
Offset: buf.ConsumeUint64(),
|
||||
Data: buf.ConsumeByteSliceCopy(p.Data),
|
||||
}
|
||||
|
||||
if p.Offset, err = buf.ConsumeUint64(); err != nil {
|
||||
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
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *FStatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = FStatPacket{
|
||||
Handle: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *FSetstatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = FSetstatPacket{
|
||||
Handle: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *ReadDirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = ReadDirPacket{
|
||||
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.
|
||||
type InitPacket struct {
|
||||
|
|
@ -33,8 +33,8 @@ func (p *InitPacket) MarshalBinary() ([]byte, error) {
|
|||
func (p *InitPacket) UnmarshalBinary(data []byte) (err error) {
|
||||
buf := NewBuffer(data)
|
||||
|
||||
if p.Version, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
*p = InitPacket{
|
||||
Version: buf.ConsumeUint32(),
|
||||
}
|
||||
|
||||
for buf.Len() > 0 {
|
||||
|
|
@ -46,7 +46,7 @@ func (p *InitPacket) UnmarshalBinary(data []byte) (err error) {
|
|||
p.Extensions = append(p.Extensions, &ext)
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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) {
|
||||
buf := NewBuffer(data)
|
||||
|
||||
if p.Version, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
*p = VersionPacket{
|
||||
Version: buf.ConsumeUint32(),
|
||||
}
|
||||
|
||||
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.
|
||||
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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *OpenPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Filename, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.PFlags, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
*p = OpenPacket{
|
||||
Filename: buf.ConsumeString(),
|
||||
PFlags: buf.ConsumeUint32(),
|
||||
}
|
||||
|
||||
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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *OpenDirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = OpenDirPacket{
|
||||
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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// smallBufferSize is an initial allocation minimal capacity.
|
||||
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 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,
|
||||
// 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 {
|
||||
PacketType PacketType
|
||||
RequestID uint32
|
||||
|
|
@ -110,19 +64,14 @@ func (p *RawPacket) MarshalBinary() ([]byte, error) {
|
|||
// The Data field will alias the passed in Buffer,
|
||||
// so the buffer passed in should not be reused before RawPacket.Reset().
|
||||
func (p *RawPacket) UnmarshalFrom(buf *Buffer) error {
|
||||
typ, err := buf.ConsumeUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.PacketType = PacketType(typ)
|
||||
|
||||
if p.RequestID, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
*p = RawPacket{
|
||||
PacketType: PacketType(buf.ConsumeUint8()),
|
||||
RequestID: buf.ConsumeUint32(),
|
||||
}
|
||||
|
||||
p.Data = *buf
|
||||
return nil
|
||||
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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,
|
||||
// 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 {
|
||||
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),
|
||||
// so the buffer passed in should not be reused before RequestPacket.Reset().
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Request, err = newPacketFromType(PacketType(typ))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.RequestID, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
*p = RequestPacket{
|
||||
RequestID: buf.ConsumeUint32(),
|
||||
Request: req,
|
||||
}
|
||||
|
||||
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.
|
||||
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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *LStatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = LStatPacket{
|
||||
Path: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *SetstatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = SetstatPacket{
|
||||
Path: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *RemovePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = RemovePacket{
|
||||
Path: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *MkdirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = MkdirPacket{
|
||||
Path: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *RmdirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = RmdirPacket{
|
||||
Path: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *RealPathPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = RealPathPacket{
|
||||
Path: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *StatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = StatPacket{
|
||||
Path: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *RenamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.OldPath, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = RenamePacket{
|
||||
OldPath: buf.ConsumeString(),
|
||||
NewPath: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
if p.NewPath, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *ReadLinkPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = ReadLinkPacket{
|
||||
Path: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// SymlinkPacket defines the SSH_FXP_SYMLINK packet.
|
||||
//
|
||||
// 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 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 {
|
||||
LinkPath 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *SymlinkPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
// Arguments were inadvertently reversed.
|
||||
if p.TargetPath, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = SymlinkPacket{
|
||||
// Arguments were inadvertently reversed.
|
||||
TargetPath: buf.ConsumeString(),
|
||||
LinkPath: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
if p.LinkPath, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
|
|
|||
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.
|
||||
// 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 (
|
||||
"fmt"
|
||||
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
// 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 {
|
||||
StatusCode Status
|
||||
ErrorMessage string
|
||||
|
|
@ -19,7 +19,7 @@ func (p *StatusPacket) Error() 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,
|
||||
|
|
@ -57,21 +57,13 @@ func (p *StatusPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []
|
|||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *StatusPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
statusCode, err := buf.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.StatusCode = Status(statusCode)
|
||||
|
||||
if p.ErrorMessage, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = StatusPacket{
|
||||
StatusCode: Status(buf.ConsumeUint32()),
|
||||
ErrorMessage: buf.ConsumeString(),
|
||||
LanguageTag: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
if p.LanguageTag, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *HandlePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
*p = HandlePacket{
|
||||
Handle: buf.ConsumeString(),
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (p *DataPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
data, err := buf.ConsumeByteSlice()
|
||||
if err != nil {
|
||||
return err
|
||||
*p = DataPacket{
|
||||
Data: buf.ConsumeByteSliceCopy(p.Data),
|
||||
}
|
||||
|
||||
if len(p.Data) < len(data) {
|
||||
p.Data = make([]byte, len(data))
|
||||
}
|
||||
|
||||
n := copy(p.Data, data)
|
||||
p.Data = p.Data[:n]
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *NamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
count, err := buf.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
count := buf.ConsumeCount()
|
||||
if buf.Err != nil {
|
||||
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
|
||||
if err := e.UnmarshalFrom(buf); err != nil {
|
||||
return err
|
||||
|
|
@ -209,7 +196,7 @@ func (p *NamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
|||
p.Entries = append(p.Entries, &e)
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Err
|
||||
}
|
||||
|
||||
// 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)
|
||||
gid = lsFormatID(sys.GID)
|
||||
default:
|
||||
if fiExt, ok := dirent.(FileInfoUidGid); ok {
|
||||
uid = lsFormatID(fiExt.Uid())
|
||||
gid = lsFormatID(fiExt.Gid())
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
//// packet ordering
|
||||
// // packet ordering
|
||||
func (s *packetManager) newOrderID() uint32 {
|
||||
s.packetCount++
|
||||
return s.packetCount
|
||||
|
|
@ -89,7 +89,7 @@ func (o orderedPackets) Sort() {
|
|||
})
|
||||
}
|
||||
|
||||
//// packet registry
|
||||
// // packet registry
|
||||
// register incoming packets to be handled
|
||||
func (s *packetManager) incomingPacket(pkt orderedRequest) {
|
||||
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()
|
||||
}
|
||||
|
||||
//// define types by adding methods
|
||||
// // define types by adding methods
|
||||
// hasPath
|
||||
func (p *sshFxpLstatPacket) 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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -281,6 +290,11 @@ func recvPacket(r io.Reader, alloc *allocator, orderID uint32) (uint8, []byte, e
|
|||
b = make([]byte, length)
|
||||
}
|
||||
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)
|
||||
return 0, nil, err
|
||||
}
|
||||
|
|
@ -522,7 +536,12 @@ func (p *sshFxpRmdirPacket) UnmarshalBinary(b []byte) error {
|
|||
}
|
||||
|
||||
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
|
||||
Linkpath string
|
||||
}
|
||||
|
|
@ -1242,7 +1261,7 @@ func (p *sshFxpExtendedPacketPosixRename) UnmarshalBinary(b []byte) error {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
@ -1271,6 +1290,6 @@ func (p *sshFxpExtendedPacketHardlink) UnmarshalBinary(b []byte) error {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
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
|
||||
|
||||
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 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")
|
||||
|
|
@ -434,7 +419,7 @@ func (fs *root) readdir(pathname string) ([]os.FileInfo, error) {
|
|||
return files, nil
|
||||
}
|
||||
|
||||
func (fs *root) readlink(pathname string) (string, error) {
|
||||
func (fs *root) Readlink(pathname string) (string, error) {
|
||||
file, err := fs.lfetch(pathname)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
@ -464,19 +449,10 @@ func (fs *root) Lstat(r *Request) (ListerAt, error) {
|
|||
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
|
||||
type root struct {
|
||||
rootFile *memFile
|
||||
mockErr error
|
||||
startDirectory string
|
||||
rootFile *memFile
|
||||
mockErr error
|
||||
|
||||
mu sync.Mutex
|
||||
files map[string]*memFile
|
||||
|
|
@ -534,8 +510,8 @@ func (fs *root) exists(path string) bool {
|
|||
return err != os.ErrNotExist
|
||||
}
|
||||
|
||||
func (fs *root) fetch(path string) (*memFile, error) {
|
||||
file, err := fs.lfetch(path)
|
||||
func (fs *root) fetch(pathname string) (*memFile, error) {
|
||||
file, err := fs.lfetch(pathname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -546,7 +522,12 @@ func (fs *root) fetch(path string) (*memFile, error) {
|
|||
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 {
|
||||
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
|
||||
// Note in cases of an error, the error text will be sent to the client.
|
||||
// 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 {
|
||||
Filelist(*Request) (ListerAt, error)
|
||||
}
|
||||
|
|
@ -87,12 +92,33 @@ type LstatFileLister interface {
|
|||
}
|
||||
|
||||
// RealPathFileLister is a FileLister that implements the Realpath method.
|
||||
// We use "/" as start directory for relative paths, implementing this
|
||||
// interface you can customize the start directory.
|
||||
// The built-in RealPath implementation does not resolve symbolic links.
|
||||
// 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.
|
||||
//
|
||||
// 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 {
|
||||
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
|
||||
RealPath(string) string
|
||||
}
|
||||
|
|
@ -105,11 +131,19 @@ type NameLookupFileLister interface {
|
|||
LookupGroupName(string) string
|
||||
}
|
||||
|
||||
// ListerAt does for file lists what io.ReaderAt does for files.
|
||||
// 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).
|
||||
// ListerAt does for file lists what io.ReaderAt does for files, i.e. a []os.FileInfo buffer is passed to the ListAt function
|
||||
// and the entries that are populated in the buffer will be passed to the client.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
type ListerAt interface {
|
||||
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
|
||||
|
||||
package sftp
|
||||
|
||||
import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
|
@ -15,20 +14,3 @@ func fakeFileInfoSys() interface{} {
|
|||
func testOsSys(sys interface{}) error {
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
### 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))
|
||||
case *sshFxpRealpathPacket:
|
||||
var realPath string
|
||||
if realPather, ok := rs.Handlers.FileList.(RealPathFileLister); ok {
|
||||
realPath = realPather.RealPath(pkt.getPath())
|
||||
} else {
|
||||
var err error
|
||||
|
||||
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())
|
||||
}
|
||||
rpkt = cleanPacketPath(pkt, realPath)
|
||||
if err != nil {
|
||||
rpkt = statusFromError(pkt.ID, err)
|
||||
} else {
|
||||
rpkt = cleanPacketPath(pkt, realPath)
|
||||
}
|
||||
case *sshFxpOpendirPacket:
|
||||
request := requestFromPacket(ctx, pkt, rs.startDirectory)
|
||||
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
|
||||
|
||||
package sftp
|
||||
|
|
@ -21,7 +22,3 @@ func testOsSys(sys interface{}) error {
|
|||
}
|
||||
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)
|
||||
// this makes Request.Target the linkpath, and Request.Filepath the target.
|
||||
request.Target = cleanPathWithBase(baseDir, p.Linkpath)
|
||||
request.Filepath = p.Targetpath
|
||||
case *sshFxpExtendedPacketHardlink:
|
||||
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)
|
||||
case "List":
|
||||
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)
|
||||
default:
|
||||
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
|
||||
func requestMethod(p requestPacket) (method string) {
|
||||
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
|
||||
|
||||
import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
|
@ -13,32 +11,3 @@ func fakeFileInfoSys() interface{} {
|
|||
func testOsSys(sys interface{}) error {
|
||||
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.
|
||||
// This is intended to provide the sftp subsystem to an ssh server daemon.
|
||||
// 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 {
|
||||
*serverConn
|
||||
debugStream io.Writer
|
||||
|
|
@ -33,6 +33,7 @@ type Server struct {
|
|||
openFiles map[string]*os.File
|
||||
openFilesLock sync.RWMutex
|
||||
handleCount int
|
||||
workDir 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 {
|
||||
pktType fxp
|
||||
pktBytes []byte
|
||||
|
|
@ -174,7 +185,7 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
}
|
||||
case *sshFxpStatPacket:
|
||||
// stat the requested file
|
||||
info, err := os.Stat(toLocalPath(p.Path))
|
||||
info, err := os.Stat(s.toLocalPath(p.Path))
|
||||
rpkt = &sshFxpStatResponse{
|
||||
ID: p.ID,
|
||||
info: info,
|
||||
|
|
@ -184,7 +195,7 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
}
|
||||
case *sshFxpLstatPacket:
|
||||
// stat the requested file
|
||||
info, err := os.Lstat(toLocalPath(p.Path))
|
||||
info, err := os.Lstat(s.toLocalPath(p.Path))
|
||||
rpkt = &sshFxpStatResponse{
|
||||
ID: p.ID,
|
||||
info: info,
|
||||
|
|
@ -208,24 +219,24 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
}
|
||||
case *sshFxpMkdirPacket:
|
||||
// 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)
|
||||
case *sshFxpRmdirPacket:
|
||||
err := os.Remove(toLocalPath(p.Path))
|
||||
err := os.Remove(s.toLocalPath(p.Path))
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
case *sshFxpRemovePacket:
|
||||
err := os.Remove(toLocalPath(p.Filename))
|
||||
err := os.Remove(s.toLocalPath(p.Filename))
|
||||
rpkt = statusFromError(p.ID, err)
|
||||
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)
|
||||
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)
|
||||
case *sshFxpClosePacket:
|
||||
rpkt = statusFromError(p.ID, s.closeHandle(p.Handle))
|
||||
case *sshFxpReadlinkPacket:
|
||||
f, err := os.Readlink(toLocalPath(p.Path))
|
||||
f, err := os.Readlink(s.toLocalPath(p.Path))
|
||||
rpkt = &sshFxpNamePacket{
|
||||
ID: p.ID,
|
||||
NameAttrs: []*sshFxpNameAttr{
|
||||
|
|
@ -240,7 +251,7 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
rpkt = statusFromError(p.ID, err)
|
||||
}
|
||||
case *sshFxpRealpathPacket:
|
||||
f, err := filepath.Abs(toLocalPath(p.Path))
|
||||
f, err := filepath.Abs(s.toLocalPath(p.Path))
|
||||
f = cleanPath(f)
|
||||
rpkt = &sshFxpNamePacket{
|
||||
ID: p.ID,
|
||||
|
|
@ -256,13 +267,14 @@ func handlePacket(s *Server, p orderedRequest) error {
|
|||
rpkt = statusFromError(p.ID, err)
|
||||
}
|
||||
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)
|
||||
} else if !stat.IsDir() {
|
||||
rpkt = statusFromError(p.ID, &os.PathError{
|
||||
Path: p.Path, Err: syscall.ENOTDIR})
|
||||
Path: lp, Err: syscall.ENOTDIR,
|
||||
})
|
||||
} else {
|
||||
rpkt = (&sshFxpOpenPacket{
|
||||
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
|
||||
// is stopped.
|
||||
// is stopped. It returns nil if the server exits cleanly.
|
||||
func (svr *Server) Serve() error {
|
||||
defer func() {
|
||||
if svr.pktMgr.alloc != nil {
|
||||
|
|
@ -341,6 +353,10 @@ func (svr *Server) Serve() error {
|
|||
for {
|
||||
pktType, pktBytes, err = svr.serverConn.recvPacket(svr.pktMgr.getNextOrderID())
|
||||
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
|
||||
break
|
||||
}
|
||||
|
|
@ -446,7 +462,7 @@ func (p *sshFxpOpenPacket) respond(svr *Server) responsePacket {
|
|||
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 {
|
||||
return statusFromError(p.ID, err)
|
||||
}
|
||||
|
|
@ -484,7 +500,7 @@ func (p *sshFxpSetstatPacket) respond(svr *Server) responsePacket {
|
|||
b := p.Attrs.([]byte)
|
||||
var err error
|
||||
|
||||
p.Path = toLocalPath(p.Path)
|
||||
p.Path = svr.toLocalPath(p.Path)
|
||||
|
||||
debug("setstat name \"%s\"", p.Path)
|
||||
if (p.Flags & sshFileXferAttrSize) != 0 {
|
||||
|
|
@ -603,13 +619,15 @@ func statusFromError(id uint32, err error) *sshFxpStatusPacket {
|
|||
return ret
|
||||
}
|
||||
|
||||
switch e := err.(type) {
|
||||
case fxerr:
|
||||
if errors.Is(err, io.EOF) {
|
||||
ret.StatusError.Code = sshFxEOF
|
||||
return ret
|
||||
}
|
||||
|
||||
var e fxerr
|
||||
if errors.As(err, &e) {
|
||||
ret.StatusError.Code = uint32(e)
|
||||
default:
|
||||
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
|
||||
|
||||
// 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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
|
||||
// https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
|
||||
package sftp
|
||||
|
||||
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
|
||||
|
||||
// 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
|
||||
|
||||
package sftp
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue