Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/walkdir.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gallant <jamslam@gmail.com>2019-06-06 02:01:37 +0300
committerAndrew Gallant <jamslam@gmail.com>2020-01-28 04:27:58 +0300
commit1d7293a5a1ef548ce587a0b08abce5f21571a100 (patch)
tree891328e6665280fbfbbd15351b829c04a237b054 /src/dir.rs
parente4bd92f6a791f35593185539d91f9516161ab5ac (diff)
progressag/sys
Diffstat (limited to 'src/dir.rs')
-rw-r--r--src/dir.rs100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/dir.rs b/src/dir.rs
new file mode 100644
index 0000000..667f3a4
--- /dev/null
+++ b/src/dir.rs
@@ -0,0 +1,100 @@
+#[cfg(unix)]
+use std::ffi::CStr;
+use std::io;
+#[cfg(unix)]
+use std::os::unix::io::RawFd;
+
+#[cfg(target_os = "linux")]
+use crate::os::linux;
+#[cfg(unix)]
+use crate::os::unix;
+#[cfg(unix)]
+use crate::os::unix::RawPathBuf;
+
+#[derive(Debug)]
+pub struct Cursor {
+ #[cfg(unix)]
+ dir: unix::Dir,
+ #[cfg(unix)]
+ dent: unix::DirEntry,
+ #[cfg(target_os = "linux")]
+ linux_cursor: linux::DirEntryCursor,
+}
+
+impl Cursor {
+ #[cfg(unix)]
+ pub fn new(parent: RawFd, dir_name: &CStr) -> io::Result<Cursor> {
+ let dir = unix::Dir::openat_c(parent, dir_name)?;
+ Ok(Cursor {
+ dir,
+ #[cfg(unix)]
+ dent: unix::DirEntry::empty(),
+ #[cfg(target_os = "linux")]
+ linux_cursor: linux::DirEntryCursor::new(),
+ })
+ }
+
+ /// Reset this cursor to the beginning of the given directory.
+ ///
+ /// An error is returned if the given directory could not be opened for
+ /// reading. If an error is returned, the behavior of this cursor is
+ /// unspecified until a subsequent and successful `reset` call is made.
+ #[cfg(unix)]
+ pub fn reset(&mut self, parent: RawFd, dir_name: &CStr) -> io::Result<()> {
+ self.dir = unix::Dir::openat_c(parent, dir_name)?;
+ Ok(())
+ }
+
+ #[cfg(all(unix, walkdir_getdents))]
+ pub fn read(&mut self) -> io::Result<Option<CursorEntry>> {
+ use std::os::unix::io::AsRawFd;
+
+ let c = &mut self.linux_cursor;
+ loop {
+ if c.advance() {
+ if is_dots(c.current().file_name_bytes()) {
+ continue;
+ }
+ return Ok(Some(CursorEntry { linux_dent: c.current() }));
+ }
+ if !linux::getdents(self.dir.as_raw_fd(), c)? {
+ return Ok(None);
+ }
+ // This is guaranteed since getdents returning true means
+ // that the buffer has at least one item in it.
+ assert!(c.advance());
+ if is_dots(c.current().file_name_bytes()) {
+ continue;
+ }
+ return Ok(Some(CursorEntry { linux_dent: c.current() }));
+ }
+ }
+
+ #[cfg(all(unix, not(walkdir_getdents)))]
+ pub fn read(&mut self) -> io::Result<Option<CursorEntry>> {
+ loop {
+ return if self.dir.read_into(&mut self.dent)? {
+ if is_dots(dent.file_name_bytes()) {
+ continue;
+ }
+ Ok(Some(CursorEntry { cursor: self }))
+ } else {
+ Ok(None)
+ };
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct CursorEntry<'a> {
+ #[cfg(not(all(unix, walkdir_getdents)))]
+ cursor: &'a Cursor,
+ #[cfg(all(unix, walkdir_getdents))]
+ linux_dent: linux::DirEntry<'a>,
+}
+
+impl<'a> CursorEntry<'a> {}
+
+fn is_dots(file_name: &[u8]) -> bool {
+ file_name == b"." || file_name == b".."
+}