// Package sftp implements the SSH File Transfer Protocol as described in // https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt package sftp import ( "fmt" "github.com/pkg/errors" ) const ( ssh_FXP_INIT = 1 ssh_FXP_VERSION = 2 ssh_FXP_OPEN = 3 ssh_FXP_CLOSE = 4 ssh_FXP_READ = 5 ssh_FXP_WRITE = 6 ssh_FXP_LSTAT = 7 ssh_FXP_FSTAT = 8 ssh_FXP_SETSTAT = 9 ssh_FXP_FSETSTAT = 10 ssh_FXP_OPENDIR = 11 ssh_FXP_READDIR = 12 ssh_FXP_REMOVE = 13 ssh_FXP_MKDIR = 14 ssh_FXP_RMDIR = 15 ssh_FXP_REALPATH = 16 ssh_FXP_STAT = 17 ssh_FXP_RENAME = 18 ssh_FXP_READLINK = 19 ssh_FXP_SYMLINK = 20 ssh_FXP_STATUS = 101 ssh_FXP_HANDLE = 102 ssh_FXP_DATA = 103 ssh_FXP_NAME = 104 ssh_FXP_ATTRS = 105 ssh_FXP_EXTENDED = 200 ssh_FXP_EXTENDED_REPLY = 201 ) const ( ssh_FX_OK = 0 ssh_FX_EOF = 1 ssh_FX_NO_SUCH_FILE = 2 ssh_FX_PERMISSION_DENIED = 3 ssh_FX_FAILURE = 4 ssh_FX_BAD_MESSAGE = 5 ssh_FX_NO_CONNECTION = 6 ssh_FX_CONNECTION_LOST = 7 ssh_FX_OP_UNSUPPORTED = 8 // see draft-ietf-secsh-filexfer-13 // https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.1 ssh_FX_INVALID_HANDLE = 9 ssh_FX_NO_SUCH_PATH = 10 ssh_FX_FILE_ALREADY_EXISTS = 11 ssh_FX_WRITE_PROTECT = 12 ssh_FX_NO_MEDIA = 13 ssh_FX_NO_SPACE_ON_FILESYSTEM = 14 ssh_FX_QUOTA_EXCEEDED = 15 ssh_FX_UNKNOWN_PRINCIPAL = 16 ssh_FX_LOCK_CONFLICT = 17 ssh_FX_DIR_NOT_EMPTY = 18 ssh_FX_NOT_A_DIRECTORY = 19 ssh_FX_INVALID_FILENAME = 20 ssh_FX_LINK_LOOP = 21 ssh_FX_CANNOT_DELETE = 22 ssh_FX_INVALID_PARAMETER = 23 ssh_FX_FILE_IS_A_DIRECTORY = 24 ssh_FX_BYTE_RANGE_LOCK_CONFLICT = 25 ssh_FX_BYTE_RANGE_LOCK_REFUSED = 26 ssh_FX_DELETE_PENDING = 27 ssh_FX_FILE_CORRUPT = 28 ssh_FX_OWNER_INVALID = 29 ssh_FX_GROUP_INVALID = 30 ssh_FX_NO_MATCHING_BYTE_RANGE_LOCK = 31 ) const ( ssh_FXF_READ = 0x00000001 ssh_FXF_WRITE = 0x00000002 ssh_FXF_APPEND = 0x00000004 ssh_FXF_CREAT = 0x00000008 ssh_FXF_TRUNC = 0x00000010 ssh_FXF_EXCL = 0x00000020 ) type fxp uint8 func (f fxp) String() string { switch f { case ssh_FXP_INIT: return "SSH_FXP_INIT" case ssh_FXP_VERSION: return "SSH_FXP_VERSION" case ssh_FXP_OPEN: return "SSH_FXP_OPEN" case ssh_FXP_CLOSE: return "SSH_FXP_CLOSE" case ssh_FXP_READ: return "SSH_FXP_READ" case ssh_FXP_WRITE: return "SSH_FXP_WRITE" case ssh_FXP_LSTAT: return "SSH_FXP_LSTAT" case ssh_FXP_FSTAT: return "SSH_FXP_FSTAT" case ssh_FXP_SETSTAT: return "SSH_FXP_SETSTAT" case ssh_FXP_FSETSTAT: return "SSH_FXP_FSETSTAT" case ssh_FXP_OPENDIR: return "SSH_FXP_OPENDIR" case ssh_FXP_READDIR: return "SSH_FXP_READDIR" case ssh_FXP_REMOVE: return "SSH_FXP_REMOVE" case ssh_FXP_MKDIR: return "SSH_FXP_MKDIR" case ssh_FXP_RMDIR: return "SSH_FXP_RMDIR" case ssh_FXP_REALPATH: return "SSH_FXP_REALPATH" case ssh_FXP_STAT: return "SSH_FXP_STAT" case ssh_FXP_RENAME: return "SSH_FXP_RENAME" case ssh_FXP_READLINK: return "SSH_FXP_READLINK" case ssh_FXP_SYMLINK: return "SSH_FXP_SYMLINK" case ssh_FXP_STATUS: return "SSH_FXP_STATUS" case ssh_FXP_HANDLE: return "SSH_FXP_HANDLE" case ssh_FXP_DATA: return "SSH_FXP_DATA" case ssh_FXP_NAME: return "SSH_FXP_NAME" case ssh_FXP_ATTRS: return "SSH_FXP_ATTRS" case ssh_FXP_EXTENDED: return "SSH_FXP_EXTENDED" case ssh_FXP_EXTENDED_REPLY: return "SSH_FXP_EXTENDED_REPLY" default: return "unknown" } } type fx uint8 func (f fx) String() string { switch f { case ssh_FX_OK: return "SSH_FX_OK" case ssh_FX_EOF: return "SSH_FX_EOF" case ssh_FX_NO_SUCH_FILE: return "SSH_FX_NO_SUCH_FILE" case ssh_FX_PERMISSION_DENIED: return "SSH_FX_PERMISSION_DENIED" case ssh_FX_FAILURE: return "SSH_FX_FAILURE" case ssh_FX_BAD_MESSAGE: return "SSH_FX_BAD_MESSAGE" case ssh_FX_NO_CONNECTION: return "SSH_FX_NO_CONNECTION" case ssh_FX_CONNECTION_LOST: return "SSH_FX_CONNECTION_LOST" case ssh_FX_OP_UNSUPPORTED: return "SSH_FX_OP_UNSUPPORTED" default: return "unknown" } } type unexpectedPacketErr struct { want, got uint8 } func (u *unexpectedPacketErr) Error() string { return fmt.Sprintf("sftp: unexpected packet: want %v, got %v", fxp(u.want), fxp(u.got)) } func unimplementedPacketErr(u uint8) error { return errors.Errorf("sftp: unimplemented packet type: got %v", fxp(u)) } type unexpectedIDErr struct{ want, got uint32 } func (u *unexpectedIDErr) Error() string { return fmt.Sprintf("sftp: unexpected id: want %v, got %v", u.want, u.got) } func unimplementedSeekWhence(whence int) error { return errors.Errorf("sftp: unimplemented seek whence %v", whence) } func unexpectedCount(want, got uint32) error { return errors.Errorf("sftp: unexpected count: want %v, got %v", want, got) } type unexpectedVersionErr struct{ want, got uint32 } func (u *unexpectedVersionErr) Error() string { return fmt.Sprintf("sftp: unexpected server version: want %v, got %v", u.want, u.got) } // A StatusError is returned when an SFTP operation fails, and provides // additional information about the failure. type StatusError struct { Code uint32 msg, lang string } func (s *StatusError) Error() string { return fmt.Sprintf("sftp: %q (%v)", s.msg, fx(s.Code)) }