| 1 | use std::error::Error as StdError; | 
| 2 | use std::fmt; | 
|---|
| 3 | use std::io; | 
|---|
| 4 | use std::path::PathBuf; | 
|---|
| 5 |  | 
|---|
| 6 | #[ derive(Debug, Clone, Copy)] | 
|---|
| 7 | pub(crate) enum ErrorKind { | 
|---|
| 8 | OpenFile, | 
|---|
| 9 | CreateFile, | 
|---|
| 10 | CreateDir, | 
|---|
| 11 | SyncFile, | 
|---|
| 12 | SetLen, | 
|---|
| 13 | Metadata, | 
|---|
| 14 | Clone, | 
|---|
| 15 | SetPermissions, | 
|---|
| 16 | Read, | 
|---|
| 17 | Seek, | 
|---|
| 18 | Write, | 
|---|
| 19 | Flush, | 
|---|
| 20 | ReadDir, | 
|---|
| 21 | RemoveFile, | 
|---|
| 22 | RemoveDir, | 
|---|
| 23 | Canonicalize, | 
|---|
| 24 | ReadLink, | 
|---|
| 25 | SymlinkMetadata, | 
|---|
| 26 | #[ allow(dead_code)] | 
|---|
| 27 | FileExists, | 
|---|
| 28 |  | 
|---|
| 29 | #[ cfg(windows)] | 
|---|
| 30 | SeekRead, | 
|---|
| 31 | #[ cfg(windows)] | 
|---|
| 32 | SeekWrite, | 
|---|
| 33 |  | 
|---|
| 34 | #[ cfg(unix)] | 
|---|
| 35 | ReadAt, | 
|---|
| 36 | #[ cfg(unix)] | 
|---|
| 37 | WriteAt, | 
|---|
| 38 | } | 
|---|
| 39 |  | 
|---|
| 40 | /// Contains an IO error that has a file path attached. | 
|---|
| 41 | /// | 
|---|
| 42 | /// This type is never returned directly, but is instead wrapped inside yet | 
|---|
| 43 | /// another IO error. | 
|---|
| 44 | #[ derive(Debug)] | 
|---|
| 45 | pub(crate) struct Error { | 
|---|
| 46 | kind: ErrorKind, | 
|---|
| 47 | source: io::Error, | 
|---|
| 48 | path: PathBuf, | 
|---|
| 49 | } | 
|---|
| 50 |  | 
|---|
| 51 | impl Error { | 
|---|
| 52 | pub fn build(source: io::Error, kind: ErrorKind, path: impl Into<PathBuf>) -> io::Error { | 
|---|
| 53 | io::Error::new( | 
|---|
| 54 | source.kind(), | 
|---|
| 55 | Self { | 
|---|
| 56 | kind, | 
|---|
| 57 | source, | 
|---|
| 58 | path: path.into(), | 
|---|
| 59 | }, | 
|---|
| 60 | ) | 
|---|
| 61 | } | 
|---|
| 62 | } | 
|---|
| 63 |  | 
|---|
| 64 | impl fmt::Display for Error { | 
|---|
| 65 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | 
|---|
| 66 | use ErrorKind::*; | 
|---|
| 67 |  | 
|---|
| 68 | let path = self.path.display(); | 
|---|
| 69 |  | 
|---|
| 70 | match self.kind { | 
|---|
| 71 | OpenFile => write!(formatter, "failed to open file `{} `", path), | 
|---|
| 72 | CreateFile => write!(formatter, "failed to create file `{} `", path), | 
|---|
| 73 | CreateDir => write!(formatter, "failed to create directory `{} `", path), | 
|---|
| 74 | SyncFile => write!(formatter, "failed to sync file `{} `", path), | 
|---|
| 75 | SetLen => write!(formatter, "failed to set length of file `{} `", path), | 
|---|
| 76 | Metadata => write!(formatter, "failed to query metadata of file `{} `", path), | 
|---|
| 77 | Clone => write!(formatter, "failed to clone handle for file `{} `", path), | 
|---|
| 78 | SetPermissions => write!(formatter, "failed to set permissions for file `{} `", path), | 
|---|
| 79 | Read => write!(formatter, "failed to read from file `{} `", path), | 
|---|
| 80 | Seek => write!(formatter, "failed to seek in file `{} `", path), | 
|---|
| 81 | Write => write!(formatter, "failed to write to file `{} `", path), | 
|---|
| 82 | Flush => write!(formatter, "failed to flush file `{} `", path), | 
|---|
| 83 | ReadDir => write!(formatter, "failed to read directory `{} `", path), | 
|---|
| 84 | RemoveFile => write!(formatter, "failed to remove file `{} `", path), | 
|---|
| 85 | RemoveDir => write!(formatter, "failed to remove directory `{} `", path), | 
|---|
| 86 | Canonicalize => write!(formatter, "failed to canonicalize path `{} `", path), | 
|---|
| 87 | ReadLink => write!(formatter, "failed to read symbolic link `{} `", path), | 
|---|
| 88 | SymlinkMetadata => write!(formatter, "failed to query metadata of symlink `{} `", path), | 
|---|
| 89 | FileExists => write!(formatter, "failed to check file existance `{} `", path), | 
|---|
| 90 |  | 
|---|
| 91 | #[ cfg(windows)] | 
|---|
| 92 | SeekRead => write!(formatter, "failed to seek and read from `{}`", path), | 
|---|
| 93 | #[ cfg(windows)] | 
|---|
| 94 | SeekWrite => write!(formatter, "failed to seek and write to `{}`", path), | 
|---|
| 95 |  | 
|---|
| 96 | #[ cfg(unix)] | 
|---|
| 97 | ReadAt => write!(formatter, "failed to read with offset from `{} `", path), | 
|---|
| 98 | #[ cfg(unix)] | 
|---|
| 99 | WriteAt => write!(formatter, "failed to write with offset to `{} `", path), | 
|---|
| 100 | } | 
|---|
| 101 | } | 
|---|
| 102 | } | 
|---|
| 103 |  | 
|---|
| 104 | impl StdError for Error { | 
|---|
| 105 | fn cause(&self) -> Option<&dyn StdError> { | 
|---|
| 106 | self.source() | 
|---|
| 107 | } | 
|---|
| 108 |  | 
|---|
| 109 | fn source(&self) -> Option<&(dyn StdError + 'static)> { | 
|---|
| 110 | Some(&self.source) | 
|---|
| 111 | } | 
|---|
| 112 | } | 
|---|
| 113 |  | 
|---|
| 114 | #[ derive(Debug, Clone, Copy)] | 
|---|
| 115 | pub(crate) enum SourceDestErrorKind { | 
|---|
| 116 | Copy, | 
|---|
| 117 | HardLink, | 
|---|
| 118 | Rename, | 
|---|
| 119 | SoftLink, | 
|---|
| 120 |  | 
|---|
| 121 | #[ cfg(unix)] | 
|---|
| 122 | Symlink, | 
|---|
| 123 |  | 
|---|
| 124 | #[ cfg(windows)] | 
|---|
| 125 | SymlinkDir, | 
|---|
| 126 | #[ cfg(windows)] | 
|---|
| 127 | SymlinkFile, | 
|---|
| 128 | } | 
|---|
| 129 |  | 
|---|
| 130 | /// Error type used by functions like `fs::copy` that holds two paths. | 
|---|
| 131 | #[ derive(Debug)] | 
|---|
| 132 | pub(crate) struct SourceDestError { | 
|---|
| 133 | kind: SourceDestErrorKind, | 
|---|
| 134 | source: io::Error, | 
|---|
| 135 | from_path: PathBuf, | 
|---|
| 136 | to_path: PathBuf, | 
|---|
| 137 | } | 
|---|
| 138 |  | 
|---|
| 139 | impl SourceDestError { | 
|---|
| 140 | pub fn build( | 
|---|
| 141 | source: io::Error, | 
|---|
| 142 | kind: SourceDestErrorKind, | 
|---|
| 143 | from_path: impl Into<PathBuf>, | 
|---|
| 144 | to_path: impl Into<PathBuf>, | 
|---|
| 145 | ) -> io::Error { | 
|---|
| 146 | io::Error::new( | 
|---|
| 147 | source.kind(), | 
|---|
| 148 | Self { | 
|---|
| 149 | kind, | 
|---|
| 150 | source, | 
|---|
| 151 | from_path: from_path.into(), | 
|---|
| 152 | to_path: to_path.into(), | 
|---|
| 153 | }, | 
|---|
| 154 | ) | 
|---|
| 155 | } | 
|---|
| 156 | } | 
|---|
| 157 |  | 
|---|
| 158 | impl fmt::Display for SourceDestError { | 
|---|
| 159 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | 
|---|
| 160 | let from = self.from_path.display(); | 
|---|
| 161 | let to = self.to_path.display(); | 
|---|
| 162 | match self.kind { | 
|---|
| 163 | SourceDestErrorKind::Copy => { | 
|---|
| 164 | write!(formatter, "failed to copy file from {}  to {} ", from, to) | 
|---|
| 165 | } | 
|---|
| 166 | SourceDestErrorKind::HardLink => { | 
|---|
| 167 | write!(formatter, "failed to hardlink file from {}  to {} ", from, to) | 
|---|
| 168 | } | 
|---|
| 169 | SourceDestErrorKind::Rename => { | 
|---|
| 170 | write!(formatter, "failed to rename file from {}  to {} ", from, to) | 
|---|
| 171 | } | 
|---|
| 172 | SourceDestErrorKind::SoftLink => { | 
|---|
| 173 | write!(formatter, "failed to softlink file from {}  to {} ", from, to) | 
|---|
| 174 | } | 
|---|
| 175 |  | 
|---|
| 176 | #[ cfg(unix)] | 
|---|
| 177 | SourceDestErrorKind::Symlink => { | 
|---|
| 178 | write!(formatter, "failed to symlink file from {}  to {} ", from, to) | 
|---|
| 179 | } | 
|---|
| 180 |  | 
|---|
| 181 | #[ cfg(windows)] | 
|---|
| 182 | SourceDestErrorKind::SymlinkFile => { | 
|---|
| 183 | write!(formatter, "failed to symlink file from {} to {}", from, to) | 
|---|
| 184 | } | 
|---|
| 185 | #[ cfg(windows)] | 
|---|
| 186 | SourceDestErrorKind::SymlinkDir => { | 
|---|
| 187 | write!(formatter, "failed to symlink dir from {} to {}", from, to) | 
|---|
| 188 | } | 
|---|
| 189 | } | 
|---|
| 190 | } | 
|---|
| 191 | } | 
|---|
| 192 |  | 
|---|
| 193 | impl StdError for SourceDestError { | 
|---|
| 194 | fn cause(&self) -> Option<&dyn StdError> { | 
|---|
| 195 | self.source() | 
|---|
| 196 | } | 
|---|
| 197 |  | 
|---|
| 198 | fn source(&self) -> Option<&(dyn StdError + 'static)> { | 
|---|
| 199 | Some(&self.source) | 
|---|
| 200 | } | 
|---|
| 201 | } | 
|---|
| 202 |  | 
|---|