Skip to content

Commit 53b8037

Browse files
committed
Add directory support to smbc
1 parent 7bf7625 commit 53b8037

File tree

2 files changed

+104
-5
lines changed

2 files changed

+104
-5
lines changed

src/lib.rs

-5
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@
2424
//!
2525
//! Files are represented by [`SmbFile`](struct.SmbFile.html).
2626
//!
27-
//! Basic example:
28-
//! ```rust
29-
//! fn load
30-
//! # fn main() {}
31-
//! ```
3227
3328
#[macro_use]
3429
extern crate log;

src/smbc.rs

+104
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
2121
// imports {{{1
2222
use std::default::Default;
23+
use std::ffi::CStr;
2324
use std::io;
2425
use std::mem;
2526
use std::panic;
27+
use std::path::PathBuf;
2628
use std::ptr;
2729

2830
use std::borrow::Cow;
@@ -126,6 +128,82 @@ pub struct SmbFile<'a: 'b, 'b> {
126128
}
127129
// 1}}}
128130

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+
129207
/// Default (dummy) credential `WORKGROUP\guest` with empty password
130208
const DEF_CRED: (Cow<'static, str>, Cow<'static, str>, Cow<'static, str>) = (Cow::Borrowed("WORKGROUP"), Cow::Borrowed("guest"), Cow::Borrowed(""));
131209

@@ -233,6 +311,23 @@ impl<'a> SmbClient<'a> {
233311
self.open_ro(path)
234312
}
235313

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+
236331
/// Open write-only [`SmbFile`](struct.SmbFile.html) defined by SMB `path`.
237332
///
238333
/// If file doesn't exists it will be created.
@@ -482,4 +577,13 @@ impl<'a, 'b> Drop for SmbFile<'a, 'b> {
482577
} // }}}
483578
// 1}}}
484579

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+
}
485589
// vim: fen:fdm=marker:fdl=1:

0 commit comments

Comments
 (0)