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