| 
									
										
										
										
											2013-11-05 08:25:17 +08:00
										 |  |  | // Package sftp implements the SSH File Transfer Protocol as described in
 | 
					
						
							| 
									
										
										
										
											2017-10-02 08:55:39 +08:00
										 |  |  | // https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
 | 
					
						
							| 
									
										
										
										
											2013-11-05 08:25:17 +08:00
										 |  |  | package sftp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2013-11-05 11:36:38 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2016-05-19 13:16:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/pkg/errors" | 
					
						
							| 
									
										
										
										
											2013-11-05 08:25:17 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	sshFxpInit          = 1 | 
					
						
							|  |  |  | 	sshFxpVersion       = 2 | 
					
						
							|  |  |  | 	sshFxpOpen          = 3 | 
					
						
							|  |  |  | 	sshFxpClose         = 4 | 
					
						
							|  |  |  | 	sshFxpRead          = 5 | 
					
						
							|  |  |  | 	sshFxpWrite         = 6 | 
					
						
							|  |  |  | 	sshFxpLstat         = 7 | 
					
						
							|  |  |  | 	sshFxpFstat         = 8 | 
					
						
							|  |  |  | 	sshFxpSetstat       = 9 | 
					
						
							|  |  |  | 	sshFxpFsetstat      = 10 | 
					
						
							|  |  |  | 	sshFxpOpendir       = 11 | 
					
						
							|  |  |  | 	sshFxpReaddir       = 12 | 
					
						
							|  |  |  | 	sshFxpRemove        = 13 | 
					
						
							|  |  |  | 	sshFxpMkdir         = 14 | 
					
						
							|  |  |  | 	sshFxpRmdir         = 15 | 
					
						
							|  |  |  | 	sshFxpRealpath      = 16 | 
					
						
							|  |  |  | 	sshFxpStat          = 17 | 
					
						
							|  |  |  | 	sshFxpRename        = 18 | 
					
						
							|  |  |  | 	sshFxpReadlink      = 19 | 
					
						
							|  |  |  | 	sshFxpSymlink       = 20 | 
					
						
							|  |  |  | 	sshFxpStatus        = 101 | 
					
						
							|  |  |  | 	sshFxpHandle        = 102 | 
					
						
							|  |  |  | 	sshFxpData          = 103 | 
					
						
							|  |  |  | 	sshFxpName          = 104 | 
					
						
							|  |  |  | 	sshFxpAttrs         = 105 | 
					
						
							|  |  |  | 	sshFxpExtended      = 200 | 
					
						
							|  |  |  | 	sshFxpExtendedReply = 201 | 
					
						
							| 
									
										
										
										
											2013-11-06 08:04:26 +08:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-06 08:04:26 +08:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	sshFxOk               = 0 | 
					
						
							|  |  |  | 	sshFxEOF              = 1 | 
					
						
							|  |  |  | 	sshFxNoSuchFile       = 2 | 
					
						
							|  |  |  | 	sshFxPermissionDenied = 3 | 
					
						
							|  |  |  | 	sshFxFailure          = 4 | 
					
						
							|  |  |  | 	sshFxBadMessage       = 5 | 
					
						
							|  |  |  | 	sshFxNoConnection     = 6 | 
					
						
							|  |  |  | 	sshFxConnectionLost   = 7 | 
					
						
							|  |  |  | 	sshFxOPUnsupported    = 8 | 
					
						
							| 
									
										
										
										
											2015-12-24 03:26:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// see draft-ietf-secsh-filexfer-13
 | 
					
						
							|  |  |  | 	// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.1
 | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	sshFxInvalidHandle           = 9 | 
					
						
							|  |  |  | 	sshFxNoSuchPath              = 10 | 
					
						
							|  |  |  | 	sshFxFileAlreadyExists       = 11 | 
					
						
							|  |  |  | 	sshFxWriteProtect            = 12 | 
					
						
							|  |  |  | 	sshFxNoMedia                 = 13 | 
					
						
							|  |  |  | 	sshFxNoSpaceOnFilesystem     = 14 | 
					
						
							|  |  |  | 	sshFxQuotaExceeded           = 15 | 
					
						
							|  |  |  | 	sshFxUnlnownPrincipal        = 16 | 
					
						
							|  |  |  | 	sshFxLockConflict            = 17 | 
					
						
							|  |  |  | 	sshFxDitNotEmpty             = 18 | 
					
						
							|  |  |  | 	sshFxNotADirectory           = 19 | 
					
						
							|  |  |  | 	sshFxInvalidFilename         = 20 | 
					
						
							|  |  |  | 	sshFxLinkLoop                = 21 | 
					
						
							|  |  |  | 	sshFxCannotDelete            = 22 | 
					
						
							|  |  |  | 	sshFxInvalidParameter        = 23 | 
					
						
							|  |  |  | 	sshFxFileIsADirectory        = 24 | 
					
						
							|  |  |  | 	sshFxByteRangeLockConflict   = 25 | 
					
						
							|  |  |  | 	sshFxByteRangeLockRefused    = 26 | 
					
						
							|  |  |  | 	sshFxDeletePending           = 27 | 
					
						
							|  |  |  | 	sshFxFileCorrupt             = 28 | 
					
						
							|  |  |  | 	sshFxOwnerInvalid            = 29 | 
					
						
							|  |  |  | 	sshFxGroupInvalid            = 30 | 
					
						
							|  |  |  | 	sshFxNoMatchingByteRangeLock = 31 | 
					
						
							| 
									
										
										
										
											2013-11-05 08:25:17 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-06 08:04:26 +08:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	sshFxfRead   = 0x00000001 | 
					
						
							|  |  |  | 	sshFxfWrite  = 0x00000002 | 
					
						
							|  |  |  | 	sshFxfAppend = 0x00000004 | 
					
						
							|  |  |  | 	sshFxfCreat  = 0x00000008 | 
					
						
							|  |  |  | 	sshFxfTrunc  = 0x00000010 | 
					
						
							|  |  |  | 	sshFxfExcl   = 0x00000020 | 
					
						
							| 
									
										
										
										
											2013-11-06 08:04:26 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-12 01:04:56 +08:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	// supportedSFTPExtensions defines the supported extensions
 | 
					
						
							|  |  |  | 	supportedSFTPExtensions = []sshExtensionPair{ | 
					
						
							|  |  |  | 		{"hardlink@openssh.com", "1"}, | 
					
						
							|  |  |  | 		{"posix-rename@openssh.com", "1"}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sftpExtensions = supportedSFTPExtensions | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2019-08-27 15:18:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | type fxp uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (f fxp) String() string { | 
					
						
							|  |  |  | 	switch f { | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpInit: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_INIT" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpVersion: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_VERSION" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpOpen: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_OPEN" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpClose: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_CLOSE" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpRead: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_READ" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpWrite: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_WRITE" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpLstat: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_LSTAT" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpFstat: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_FSTAT" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpSetstat: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_SETSTAT" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpFsetstat: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_FSETSTAT" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpOpendir: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_OPENDIR" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpReaddir: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_READDIR" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpRemove: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_REMOVE" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpMkdir: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_MKDIR" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpRmdir: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_RMDIR" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpRealpath: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_REALPATH" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpStat: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_STAT" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpRename: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_RENAME" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpReadlink: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_READLINK" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpSymlink: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_SYMLINK" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpStatus: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_STATUS" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpHandle: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_HANDLE" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpData: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_DATA" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpName: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_NAME" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpAttrs: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_ATTRS" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpExtended: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_EXTENDED" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxpExtendedReply: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FXP_EXTENDED_REPLY" | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return "unknown" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type fx uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (f fx) String() string { | 
					
						
							|  |  |  | 	switch f { | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxOk: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FX_OK" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxEOF: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FX_EOF" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxNoSuchFile: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FX_NO_SUCH_FILE" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxPermissionDenied: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FX_PERMISSION_DENIED" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxFailure: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FX_FAILURE" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxBadMessage: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FX_BAD_MESSAGE" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxNoConnection: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FX_NO_CONNECTION" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxConnectionLost: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FX_CONNECTION_LOST" | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	case sshFxOPUnsupported: | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 		return "SSH_FX_OP_UNSUPPORTED" | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return "unknown" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-05 11:36:38 +08:00
										 |  |  | type unexpectedPacketErr struct { | 
					
						
							|  |  |  | 	want, got uint8 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (u *unexpectedPacketErr) Error() string { | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 	return fmt.Sprintf("sftp: unexpected packet: want %v, got %v", fxp(u.want), fxp(u.got)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-14 12:32:21 +08:00
										 |  |  | func unimplementedPacketErr(u uint8) error { | 
					
						
							| 
									
										
										
										
											2016-05-19 13:16:48 +08:00
										 |  |  | 	return errors.Errorf("sftp: unimplemented packet type: got %v", fxp(u)) | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-05 05:15:21 +08:00
										 |  |  | type unexpectedIDErr struct{ want, got uint32 } | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-05 05:15:21 +08:00
										 |  |  | func (u *unexpectedIDErr) Error() string { | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | 	return fmt.Sprintf("sftp: unexpected id: want %v, got %v", u.want, u.got) | 
					
						
							| 
									
										
										
										
											2013-11-05 11:36:38 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-12 03:17:53 +08:00
										 |  |  | func unimplementedSeekWhence(whence int) error { | 
					
						
							| 
									
										
										
										
											2016-05-19 13:16:48 +08:00
										 |  |  | 	return errors.Errorf("sftp: unimplemented seek whence %v", whence) | 
					
						
							| 
									
										
										
										
											2014-06-12 03:17:53 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-24 02:42:28 +08:00
										 |  |  | func unexpectedCount(want, got uint32) error { | 
					
						
							| 
									
										
										
										
											2016-05-19 13:16:48 +08:00
										 |  |  | 	return errors.Errorf("sftp: unexpected count: want %v, got %v", want, got) | 
					
						
							| 
									
										
										
										
											2014-09-24 02:42:28 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-10 02:45:30 +08:00
										 |  |  | 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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-08 04:11:16 +08:00
										 |  |  | // A StatusError is returned when an SFTP operation fails, and provides
 | 
					
						
							|  |  |  | // additional information about the failure.
 | 
					
						
							| 
									
										
										
										
											2013-11-05 12:32:04 +08:00
										 |  |  | type StatusError struct { | 
					
						
							|  |  |  | 	Code      uint32 | 
					
						
							|  |  |  | 	msg, lang string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-07 07:49:46 +08:00
										 |  |  | func (s *StatusError) Error() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("sftp: %q (%v)", s.msg, fx(s.Code)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // FxCode returns the error code typed to match against the exported codes
 | 
					
						
							|  |  |  | func (s *StatusError) FxCode() fxerr { | 
					
						
							|  |  |  | 	return fxerr(s.Code) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-11-12 01:04:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func getSupportedExtensionByName(extensionName string) (sshExtensionPair, error) { | 
					
						
							|  |  |  | 	for _, supportedExtension := range supportedSFTPExtensions { | 
					
						
							|  |  |  | 		if supportedExtension.Name == extensionName { | 
					
						
							|  |  |  | 			return supportedExtension, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return sshExtensionPair{}, fmt.Errorf("Unsupported extension: %v", extensionName) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetSFTPExtensions allows to customize the supported server extensions.
 | 
					
						
							|  |  |  | // See the variable supportedSFTPExtensions for supported extensions.
 | 
					
						
							|  |  |  | // This method accepts a slice of sshExtensionPair names for example 'hardlink@openssh.com'.
 | 
					
						
							|  |  |  | // If an invalid extension is given an error will be returned and nothing will be changed
 | 
					
						
							|  |  |  | func SetSFTPExtensions(extensions ...string) error { | 
					
						
							|  |  |  | 	tempExtensions := []sshExtensionPair{} | 
					
						
							|  |  |  | 	for _, extension := range extensions { | 
					
						
							|  |  |  | 		sftpExtension, err := getSupportedExtensionByName(extension) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		tempExtensions = append(tempExtensions, sftpExtension) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sftpExtensions = tempExtensions | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |