wezterm_ssh/sftp/
error.rs1use std::convert::TryFrom;
2use thiserror::Error;
3
4pub type SftpResult<T> = Result<T, SftpError>;
6
7#[derive(Copy, Clone, Debug, Error, Hash, PartialEq, Eq)]
9pub enum SftpError {
10 #[error("End-of-file encountered")]
12 Eof = 1,
13 #[error("File doesn't exist")]
14 NoSuchFile = 2,
15 #[error("Permission denied")]
16 PermissionDenied = 3,
17 #[error("Generic failure")]
18 Failure = 4,
19 #[error("Garbage received from server")]
20 BadMessage = 5,
21 #[error("No connection has been set up")]
22 NoConnection = 6,
23 #[error("There was a connection, but we lost it")]
24 ConnectionLost = 7,
25 #[error("Operation not supported by the server")]
26 OpUnsupported = 8,
27 #[error("Invalid file handle")]
28 InvalidHandle = 9,
29 #[error("No such file or directory path exists")]
30 NoSuchPath = 10,
31 #[error("An attempt to create an already existing file or directory has been made")]
32 FileAlreadyExists = 11,
33 #[error("We are trying to write on a write-protected filesystem")]
34 WriteProtect = 12,
35 #[error("No media in remote drive")]
36 NoMedia = 13,
37
38 #[cfg(feature = "ssh2")]
40 #[error("No space available on filesystem")]
41 NoSpaceOnFilesystem = 14,
42 #[cfg(feature = "ssh2")]
43 #[error("Quota exceeded")]
44 QuotaExceeded = 15,
45 #[cfg(feature = "ssh2")]
46 #[error("Unknown principal")]
47 UnknownPrincipal = 16,
48 #[cfg(feature = "ssh2")]
49 #[error("Filesystem lock conflict")]
50 LockConflict = 17,
51 #[cfg(feature = "ssh2")]
52 #[error("Directory is not empty")]
53 DirNotEmpty = 18,
54 #[cfg(feature = "ssh2")]
55 #[error("Operation attempted against a path that is not a directory")]
56 NotADirectory = 19,
57 #[cfg(feature = "ssh2")]
58 #[error("Filename invalid")]
59 InvalidFilename = 20,
60 #[cfg(feature = "ssh2")]
61 #[error("Symlink loop encountered")]
62 LinkLoop = 21,
63}
64
65impl SftpError {
66 pub fn from_error_code(code: i32) -> Option<SftpError> {
68 Self::try_from(code).ok()
69 }
70
71 pub fn to_error_code(self) -> i32 {
73 self as i32
74 }
75}
76
77impl TryFrom<i32> for SftpError {
78 type Error = Result<(), i32>;
79
80 fn try_from(code: i32) -> Result<Self, Self::Error> {
84 match code {
85 0 => Err(Ok(())),
87
88 1 => Ok(Self::Eof),
89 2 => Ok(Self::NoSuchFile),
90 3 => Ok(Self::PermissionDenied),
91 4 => Ok(Self::Failure),
92 5 => Ok(Self::BadMessage),
93 6 => Ok(Self::NoConnection),
94 7 => Ok(Self::ConnectionLost),
95 8 => Ok(Self::OpUnsupported),
96 9 => Ok(Self::InvalidHandle),
97 10 => Ok(Self::NoSuchPath),
98 11 => Ok(Self::FileAlreadyExists),
99 12 => Ok(Self::WriteProtect),
100 13 => Ok(Self::NoMedia),
101
102 #[cfg(feature = "ssh2")]
104 14 => Ok(Self::NoSpaceOnFilesystem),
105 #[cfg(feature = "ssh2")]
106 15 => Ok(Self::QuotaExceeded),
107 #[cfg(feature = "ssh2")]
108 16 => Ok(Self::UnknownPrincipal),
109 #[cfg(feature = "ssh2")]
110 17 => Ok(Self::LockConflict),
111 #[cfg(feature = "ssh2")]
112 18 => Ok(Self::DirNotEmpty),
113 #[cfg(feature = "ssh2")]
114 19 => Ok(Self::NotADirectory),
115 #[cfg(feature = "ssh2")]
116 20 => Ok(Self::InvalidFilename),
117 #[cfg(feature = "ssh2")]
118 21 => Ok(Self::LinkLoop),
119
120 x => Err(Err(x)),
122 }
123 }
124}
125
126#[cfg(feature = "ssh2")]
127impl TryFrom<ssh2::Error> for SftpError {
128 type Error = ssh2::Error;
129
130 fn try_from(err: ssh2::Error) -> Result<Self, Self::Error> {
131 match err.code() {
132 ssh2::ErrorCode::SFTP(x) => match Self::from_error_code(x) {
133 Some(err) => Ok(err),
134 None => Err(err),
135 },
136 _ => Err(err),
137 }
138 }
139}
140
141#[cfg(feature = "ssh2")]
142impl TryFrom<ssh2::ErrorCode> for SftpError {
143 type Error = ssh2::ErrorCode;
144
145 fn try_from(code: ssh2::ErrorCode) -> Result<Self, Self::Error> {
146 match code {
147 ssh2::ErrorCode::SFTP(x) => match Self::from_error_code(x) {
148 Some(err) => Ok(err),
149 None => Err(code),
150 },
151 x => Err(x),
152 }
153 }
154}