From 0b9863bfcb3148247986ead64683bd9add2502fa Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Wed, 21 Jun 2023 21:29:27 +0800 Subject: [PATCH] feature(libbasic): add opendirat opendirat is used to open a directory with the directory fd. --- libs/basic/src/fd_util.rs | 46 +++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/libs/basic/src/fd_util.rs b/libs/basic/src/fd_util.rs index b397472..0d41966 100644 --- a/libs/basic/src/fd_util.rs +++ b/libs/basic/src/fd_util.rs @@ -14,9 +14,9 @@ use crate::error::*; use nix::{ errno::Errno, - fcntl::{FcntlArg, FdFlag, OFlag}, + fcntl::{openat, FcntlArg, FdFlag, OFlag}, ioctl_read, - sys::stat::SFlag, + sys::stat::{Mode, SFlag}, }; /// check if the given stat.st_mode is regular file @@ -157,11 +157,33 @@ pub fn fd_get_diskseq(fd: i32) -> Result { Ok(diskseq) } +/// open the directory at fd +pub fn opendirat(dirfd: i32, flags: OFlag) -> Result { + let nfd = openat( + dirfd, + ".", + OFlag::O_RDONLY | OFlag::O_NONBLOCK | OFlag::O_DIRECTORY | OFlag::O_CLOEXEC | flags, + Mode::empty(), + ) + .context(NixSnafu)?; + + nix::dir::Dir::from_fd(nfd).context(NixSnafu) +} + #[cfg(test)] mod tests { use crate::fd_util::{stat_is_char, stat_is_reg}; - use nix::sys::stat::fstat; - use std::{fs::File, os::unix::prelude::AsRawFd, path::Path}; + use nix::{ + fcntl::{open, OFlag}, + sys::stat::{fstat, Mode}, + }; + use std::{ + fs::{remove_dir_all, File}, + os::unix::prelude::AsRawFd, + path::Path, + }; + + use super::opendirat; #[test] fn test_stats() { @@ -185,4 +207,20 @@ mod tests { let st = fstat(fd_non_char_file.as_raw_fd()).unwrap(); assert!(!stat_is_char(st.st_mode)); } + + #[test] + fn test_opendirat() { + std::fs::create_dir_all("/tmp/test_opendirat").unwrap(); + File::create("/tmp/test_opendirat/entry0").unwrap(); + File::create("/tmp/test_opendirat/entry1").unwrap(); + + let dirfd = open("/tmp/test_opendirat", OFlag::O_DIRECTORY, Mode::empty()).unwrap(); + let mut dir = opendirat(dirfd, OFlag::O_NOFOLLOW).unwrap(); + + for e in dir.iter() { + let _ = e.unwrap(); + } + + remove_dir_all("/tmp/test_opendirat").unwrap(); + } } -- 2.33.0