• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![cfg(not(target_os = "redox"))]
2 
3 use std::collections::HashMap;
4 use std::fs::File;
5 #[cfg(any(target_os = "android", target_os = "linux"))]
6 use std::mem::MaybeUninit;
7 
8 use rustix::fs::{Dir, DirEntry};
9 
10 #[test]
dir_entries()11 fn dir_entries() {
12     let tmpdir = tempfile::tempdir().expect("construct tempdir");
13     let dirfd = File::open(tmpdir.path()).expect("open tempdir as file");
14     let mut dir = Dir::read_from(dirfd).expect("construct Dir from dirfd");
15 
16     let entries = read_entries(&mut dir);
17     assert_eq!(entries.len(), 0, "no files in directory");
18 
19     let _f1 = File::create(tmpdir.path().join("file1")).expect("create file1");
20 
21     let entries = read_entries(&mut dir);
22     assert!(
23         entries.get("file1").is_some(),
24         "directory contains `file1`: {:?}",
25         entries
26     );
27     assert_eq!(entries.len(), 1);
28 
29     let _f2 = File::create(tmpdir.path().join("file2")).expect("create file1");
30     let entries = read_entries(&mut dir);
31     assert!(
32         entries.get("file1").is_some(),
33         "directory contains `file1`: {:?}",
34         entries
35     );
36     assert!(
37         entries.get("file2").is_some(),
38         "directory contains `file2`: {:?}",
39         entries
40     );
41     assert_eq!(entries.len(), 2);
42 }
43 
read_entries(dir: &mut Dir) -> HashMap<String, DirEntry>44 fn read_entries(dir: &mut Dir) -> HashMap<String, DirEntry> {
45     dir.rewind();
46     let mut out = HashMap::new();
47     while let Some(err) = dir.read() {
48         let err = err.expect("non-error entry");
49         let name = err.file_name().to_str().expect("utf8 filename").to_owned();
50         if name != "." && name != ".." {
51             out.insert(name, err);
52         }
53     }
54     out
55 }
56 
57 #[cfg(any(target_os = "android", target_os = "linux"))]
test_raw_dir(buf: &mut [MaybeUninit<u8>])58 fn test_raw_dir(buf: &mut [MaybeUninit<u8>]) {
59     use std::collections::HashSet;
60     use std::io::{Seek, SeekFrom};
61 
62     use rustix::fd::AsFd;
63     use rustix::fs::RawDir;
64 
65     fn read_raw_entries<Fd: AsFd>(dir: &mut RawDir<Fd>) -> HashSet<String> {
66         let mut out = HashSet::new();
67         while let Some(entry) = dir.next() {
68             let entry = entry.expect("non-error entry");
69             let name = entry
70                 .file_name()
71                 .to_str()
72                 .expect("utf8 filename")
73                 .to_owned();
74             if name != "." && name != ".." {
75                 out.insert(name);
76             }
77         }
78         out
79     }
80 
81     let tmpdir = tempfile::tempdir().expect("construct tempdir");
82     let mut dirfd = File::open(tmpdir.path()).expect("open tempdir as file");
83     let mut dir = RawDir::new(dirfd.try_clone().unwrap(), buf);
84 
85     let entries = read_raw_entries(&mut dir);
86     assert_eq!(entries.len(), 0, "no files in directory");
87 
88     let _f1 = File::create(tmpdir.path().join("file1")).expect("create file1");
89 
90     dirfd.seek(SeekFrom::Start(0)).unwrap();
91     let entries = read_raw_entries(&mut dir);
92     assert!(
93         entries.get("file1").is_some(),
94         "directory contains `file1`: {:?}",
95         entries
96     );
97     assert_eq!(entries.len(), 1);
98 
99     let _f2 = File::create(tmpdir.path().join("file2")).expect("create file1");
100     dirfd.seek(SeekFrom::Start(0)).unwrap();
101     let entries = read_raw_entries(&mut dir);
102     assert!(
103         entries.get("file1").is_some(),
104         "directory contains `file1`: {:?}",
105         entries
106     );
107     assert!(
108         entries.get("file2").is_some(),
109         "directory contains `file2`: {:?}",
110         entries
111     );
112     assert_eq!(entries.len(), 2);
113 }
114 
115 #[test]
116 #[cfg(any(target_os = "android", target_os = "linux"))]
raw_dir_entries_heap()117 fn raw_dir_entries_heap() {
118     // When we can depend on Rust 1.60, we can use the spare_capacity_mut version instead.
119     /*
120     let mut buf = Vec::with_capacity(8192);
121     test_raw_dir(buf.spare_capacity_mut());
122     */
123     let mut buf = [MaybeUninit::new(0); 8192];
124     test_raw_dir(&mut buf);
125 }
126 
127 #[test]
128 #[cfg(any(target_os = "android", target_os = "linux"))]
raw_dir_entries_stack()129 fn raw_dir_entries_stack() {
130     let mut buf = [MaybeUninit::uninit(); 2048];
131     test_raw_dir(&mut buf);
132 }
133 
134 #[test]
135 #[cfg(any(target_os = "android", target_os = "linux"))]
raw_dir_entries_unaligned()136 fn raw_dir_entries_unaligned() {
137     let mut buf = [MaybeUninit::uninit(); 2048];
138     let buf = &mut buf[1..];
139 
140     assert!(!(buf.as_ptr() as usize).is_power_of_two());
141 
142     test_raw_dir(buf);
143 }
144 
145 #[test]
dir_from_openat()146 fn dir_from_openat() {
147     let dirfd = rustix::fs::openat(
148         rustix::fs::cwd(),
149         ".",
150         rustix::fs::OFlags::RDONLY,
151         rustix::fs::Mode::empty(),
152     )
153     .expect("open cwd as file");
154     let _dir = Dir::read_from(dirfd).expect("construct Dir from dirfd");
155 }
156