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

dir.rs « src - github.com/windirstat/walkdir.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 667f3a491d878b42841a812ddbe0d09843c584d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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".."
}