|
20 | 20 |
|
21 | 21 | // imports {{{1
|
22 | 22 | use std::default::Default;
|
| 23 | +use std::ffi::CStr; |
23 | 24 | use std::io;
|
24 | 25 | use std::mem;
|
25 | 26 | use std::panic;
|
| 27 | +use std::path::PathBuf; |
26 | 28 | use std::ptr;
|
27 | 29 |
|
28 | 30 | use std::borrow::Cow;
|
@@ -126,6 +128,82 @@ pub struct SmbFile<'a: 'b, 'b> {
|
126 | 128 | }
|
127 | 129 | // 1}}}
|
128 | 130 |
|
| 131 | +pub struct SmbDirectory<'a: 'b, 'b> { |
| 132 | + smbc: &'b SmbClient<'a>, |
| 133 | + fd: *mut SMBCFILE, |
| 134 | +} |
| 135 | + |
| 136 | +#[derive(Debug)] |
| 137 | +pub struct DirEntry { |
| 138 | + pub path: PathBuf, |
| 139 | + pub name: String, |
| 140 | + pub comment: String, |
| 141 | + pub file_type: SmbcType, |
| 142 | +} |
| 143 | + |
| 144 | +#[derive(Debug)] |
| 145 | +pub enum SmbcType { |
| 146 | + Workgroup, |
| 147 | + Server, |
| 148 | + FileShare, |
| 149 | + PrinterShare, |
| 150 | + CommsShare, |
| 151 | + IpcShare, |
| 152 | + Dir, |
| 153 | + File, |
| 154 | + Link, |
| 155 | + Unknown, |
| 156 | +} |
| 157 | + |
| 158 | +impl From<u32> for SmbcType { |
| 159 | + fn from(i: u32) -> Self { |
| 160 | + match i { |
| 161 | + 1 => SmbcType::Workgroup, |
| 162 | + 2 => SmbcType::Server, |
| 163 | + 3 => SmbcType::FileShare, |
| 164 | + 4 => SmbcType::PrinterShare, |
| 165 | + 5 => SmbcType::CommsShare, |
| 166 | + 6 => SmbcType::IpcShare, |
| 167 | + 7 => SmbcType::Dir, |
| 168 | + 8 => SmbcType::File, |
| 169 | + 9 => SmbcType::Link, |
| 170 | + _ => SmbcType::Unknown, |
| 171 | + } |
| 172 | + } |
| 173 | +} |
| 174 | + |
| 175 | +impl<'a, 'b> Iterator for SmbDirectory<'a, 'b> { |
| 176 | + type Item = Result<DirEntry>; |
| 177 | + fn next(&mut self) -> Option<Result<DirEntry>> { |
| 178 | + unsafe { |
| 179 | + let readdir_fn = smbc_getFunctionReaddir(self.smbc.ctx).unwrap(); |
| 180 | + let next_entry = readdir_fn(self.smbc.ctx, self.fd); |
| 181 | + /* |
| 182 | + @return A pointer to a smbc_dirent structure, or NULL if an |
| 183 | + error occurs or end-of-directory is reached: |
| 184 | + - EBADF Invalid directory handle |
| 185 | + - EINVAL smbc_init() failed or has not been called |
| 186 | +
|
| 187 | + */ |
| 188 | + // TODO: How do I check for an error occuring here? |
| 189 | + if next_entry.is_null(){ |
| 190 | + // End of stream reached or error |
| 191 | + return None; |
| 192 | + } |
| 193 | + let file_name = CStr::from_ptr((*next_entry).name.as_ptr()); |
| 194 | + let comment = CStr::from_ptr((*next_entry).comment); |
| 195 | + let file_type = SmbcType::from((*next_entry).smbc_type); |
| 196 | + return Some(Ok(DirEntry { |
| 197 | + path: PathBuf::from(file_name.to_string_lossy().into_owned()), |
| 198 | + name: file_name.to_string_lossy().into_owned(), |
| 199 | + comment: comment.to_string_lossy().into_owned(), |
| 200 | + file_type: file_type, |
| 201 | + })); |
| 202 | + } |
| 203 | + } |
| 204 | +} |
| 205 | + |
| 206 | + |
129 | 207 | /// Default (dummy) credential `WORKGROUP\guest` with empty password
|
130 | 208 | const DEF_CRED: (Cow<'static, str>, Cow<'static, str>, Cow<'static, str>) = (Cow::Borrowed("WORKGROUP"), Cow::Borrowed("guest"), Cow::Borrowed(""));
|
131 | 209 |
|
@@ -233,6 +311,23 @@ impl<'a> SmbClient<'a> {
|
233 | 311 | self.open_ro(path)
|
234 | 312 | }
|
235 | 313 |
|
| 314 | + /// Open a directory used to obtain directory entries. |
| 315 | + pub fn opendir<'b, P: AsRef<str>>(&'b self, path: P) -> Result<SmbDirectory<'a, 'b>> { |
| 316 | + let path = try!(cstring(path)); |
| 317 | + unsafe { |
| 318 | + let open_fn = try_ufn!(smbc_getFunctionOpendir <- self); |
| 319 | + let fd = try!(result_from_ptr_mut(open_fn(self.ctx, path.as_ptr()))); |
| 320 | + |
| 321 | + if (fd as i64) < 0 { |
| 322 | + trace!(target: "smbc", "neg fd"); |
| 323 | + } |
| 324 | + Ok(SmbDirectory { |
| 325 | + smbc: &self, |
| 326 | + fd: fd, |
| 327 | + }) |
| 328 | + } |
| 329 | + } |
| 330 | + |
236 | 331 | /// Open write-only [`SmbFile`](struct.SmbFile.html) defined by SMB `path`.
|
237 | 332 | ///
|
238 | 333 | /// If file doesn't exists it will be created.
|
@@ -482,4 +577,13 @@ impl<'a, 'b> Drop for SmbFile<'a, 'b> {
|
482 | 577 | } // }}}
|
483 | 578 | // 1}}}
|
484 | 579 |
|
| 580 | +impl<'a, 'b> Drop for SmbDirectory<'a, 'b> { |
| 581 | + // {{{2 |
| 582 | + fn drop(&mut self) { |
| 583 | + trace!(target: "smbc", "closing directory"); |
| 584 | + unsafe { |
| 585 | + smbc_getFunctionClosedir(self.smbc.ctx).map(|f| f(self.smbc.ctx, self.fd)); |
| 586 | + } |
| 587 | + } |
| 588 | +} |
485 | 589 | // vim: fen:fdm=marker:fdl=1:
|
0 commit comments