1#![cfg(not(target_os = "redox"))] 2 3use std::collections::HashMap; 4use std::fs::File; 5#[cfg(any(target_os = "android", target_os = "linux"))] 6use std::mem::MaybeUninit; 7 8use rustix::fs::{Dir, DirEntry}; 9 10#[test] 11fn 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 44fn 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"))] 58fn 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"))] 117fn 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"))] 129fn 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"))] 136fn 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] 146fn 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