Skip to content

Commit 7479c87

Browse files
authored
Merge pull request #237 from Berrysoft:dev/new-fs
feat(fs): new fs methods
2 parents a9b0797 + baefc5c commit 7479c87

File tree

9 files changed

+647
-1
lines changed

9 files changed

+647
-1
lines changed

compio-driver/src/iour/op.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,62 @@ impl OpCode for Sync {
198198
}
199199
}
200200

201+
impl OpCode for Unlink {
202+
fn create_entry(self: Pin<&mut Self>) -> OpEntry {
203+
opcode::UnlinkAt::new(Fd(libc::AT_FDCWD), self.path.as_ptr())
204+
.flags(if self.dir { libc::AT_REMOVEDIR } else { 0 })
205+
.build()
206+
.into()
207+
}
208+
}
209+
210+
impl OpCode for CreateDir {
211+
fn create_entry(self: Pin<&mut Self>) -> OpEntry {
212+
opcode::MkDirAt::new(Fd(libc::AT_FDCWD), self.path.as_ptr())
213+
.mode(self.mode)
214+
.build()
215+
.into()
216+
}
217+
}
218+
219+
impl OpCode for Rename {
220+
fn create_entry(self: Pin<&mut Self>) -> OpEntry {
221+
opcode::RenameAt::new(
222+
Fd(libc::AT_FDCWD),
223+
self.old_path.as_ptr(),
224+
Fd(libc::AT_FDCWD),
225+
self.new_path.as_ptr(),
226+
)
227+
.build()
228+
.into()
229+
}
230+
}
231+
232+
impl OpCode for Symlink {
233+
fn create_entry(self: Pin<&mut Self>) -> OpEntry {
234+
opcode::SymlinkAt::new(
235+
Fd(libc::AT_FDCWD),
236+
self.source.as_ptr(),
237+
self.target.as_ptr(),
238+
)
239+
.build()
240+
.into()
241+
}
242+
}
243+
244+
impl OpCode for HardLink {
245+
fn create_entry(self: Pin<&mut Self>) -> OpEntry {
246+
opcode::LinkAt::new(
247+
Fd(libc::AT_FDCWD),
248+
self.source.as_ptr(),
249+
Fd(libc::AT_FDCWD),
250+
self.target.as_ptr(),
251+
)
252+
.build()
253+
.into()
254+
}
255+
}
256+
201257
impl OpCode for ShutdownSocket {
202258
fn create_entry(self: Pin<&mut Self>) -> OpEntry {
203259
opcode::Shutdown::new(Fd(self.fd), self.how())

compio-driver/src/op.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ pub use crate::sys::op::{
1515
SendVectored,
1616
};
1717
#[cfg(unix)]
18-
pub use crate::sys::op::{FileStat, OpenFile, PathStat, ReadVectoredAt, WriteVectoredAt};
18+
pub use crate::sys::op::{
19+
CreateDir, FileStat, HardLink, OpenFile, PathStat, ReadVectoredAt, Rename, Symlink, Unlink,
20+
WriteVectoredAt,
21+
};
1922
use crate::sys::{sockaddr_storage, socklen_t, RawFd};
2023

2124
/// Trait to update the buffer length inside the [`BufResult`].

compio-driver/src/poll/op.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,65 @@ impl OpCode for Sync {
288288
}
289289
}
290290

291+
impl OpCode for Unlink {
292+
fn pre_submit(self: Pin<&mut Self>) -> io::Result<Decision> {
293+
Ok(Decision::blocking_dummy())
294+
}
295+
296+
fn on_event(self: Pin<&mut Self>, _: &Event) -> Poll<io::Result<usize>> {
297+
if self.dir {
298+
syscall!(libc::rmdir(self.path.as_ptr()))?;
299+
} else {
300+
syscall!(libc::unlink(self.path.as_ptr()))?;
301+
}
302+
Poll::Ready(Ok(0))
303+
}
304+
}
305+
306+
impl OpCode for CreateDir {
307+
fn pre_submit(self: Pin<&mut Self>) -> io::Result<Decision> {
308+
Ok(Decision::blocking_dummy())
309+
}
310+
311+
fn on_event(self: Pin<&mut Self>, _: &Event) -> Poll<io::Result<usize>> {
312+
syscall!(libc::mkdir(self.path.as_ptr(), self.mode))?;
313+
Poll::Ready(Ok(0))
314+
}
315+
}
316+
317+
impl OpCode for Rename {
318+
fn pre_submit(self: Pin<&mut Self>) -> io::Result<Decision> {
319+
Ok(Decision::blocking_dummy())
320+
}
321+
322+
fn on_event(self: Pin<&mut Self>, _: &Event) -> Poll<io::Result<usize>> {
323+
syscall!(libc::rename(self.old_path.as_ptr(), self.new_path.as_ptr()))?;
324+
Poll::Ready(Ok(0))
325+
}
326+
}
327+
328+
impl OpCode for Symlink {
329+
fn pre_submit(self: Pin<&mut Self>) -> io::Result<Decision> {
330+
Ok(Decision::blocking_dummy())
331+
}
332+
333+
fn on_event(self: Pin<&mut Self>, _: &Event) -> Poll<io::Result<usize>> {
334+
syscall!(libc::symlink(self.source.as_ptr(), self.target.as_ptr()))?;
335+
Poll::Ready(Ok(0))
336+
}
337+
}
338+
339+
impl OpCode for HardLink {
340+
fn pre_submit(self: Pin<&mut Self>) -> io::Result<Decision> {
341+
Ok(Decision::blocking_dummy())
342+
}
343+
344+
fn on_event(self: Pin<&mut Self>, _: &Event) -> Poll<io::Result<usize>> {
345+
syscall!(libc::link(self.source.as_ptr(), self.target.as_ptr()))?;
346+
Poll::Ready(Ok(0))
347+
}
348+
}
349+
291350
impl OpCode for ShutdownSocket {
292351
fn pre_submit(self: Pin<&mut Self>) -> io::Result<Decision> {
293352
Ok(Decision::blocking_dummy())

compio-driver/src/unix/op.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,71 @@ impl<T: IoVectoredBuf> IntoInner for WriteVectoredAt<T> {
144144
}
145145
}
146146

147+
/// Remove file or directory.
148+
pub struct Unlink {
149+
pub(crate) path: CString,
150+
pub(crate) dir: bool,
151+
}
152+
153+
impl Unlink {
154+
/// Create [`Unlink`].
155+
pub fn new(path: CString, dir: bool) -> Self {
156+
Self { path, dir }
157+
}
158+
}
159+
160+
/// Create a directory.
161+
pub struct CreateDir {
162+
pub(crate) path: CString,
163+
pub(crate) mode: libc::mode_t,
164+
}
165+
166+
impl CreateDir {
167+
/// Create [`CreateDir`].
168+
pub fn new(path: CString, mode: libc::mode_t) -> Self {
169+
Self { path, mode }
170+
}
171+
}
172+
173+
/// Rename a file or directory.
174+
pub struct Rename {
175+
pub(crate) old_path: CString,
176+
pub(crate) new_path: CString,
177+
}
178+
179+
impl Rename {
180+
/// Create [`Rename`].
181+
pub fn new(old_path: CString, new_path: CString) -> Self {
182+
Self { old_path, new_path }
183+
}
184+
}
185+
186+
/// Create a symlink.
187+
pub struct Symlink {
188+
pub(crate) source: CString,
189+
pub(crate) target: CString,
190+
}
191+
192+
impl Symlink {
193+
/// Create [`Symlink`]. `target` is a symlink to `source`.
194+
pub fn new(source: CString, target: CString) -> Self {
195+
Self { source, target }
196+
}
197+
}
198+
199+
/// Create a hard link.
200+
pub struct HardLink {
201+
pub(crate) source: CString,
202+
pub(crate) target: CString,
203+
}
204+
205+
impl HardLink {
206+
/// Create [`HardLink`]. `target` is a hard link to `source`.
207+
pub fn new(source: CString, target: CString) -> Self {
208+
Self { source, target }
209+
}
210+
}
211+
147212
impl ShutdownSocket {
148213
pub(crate) fn how(&self) -> i32 {
149214
match self.how {

compio-fs/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub use metadata::*;
2020
mod stdio;
2121
pub use stdio::*;
2222

23+
mod utils;
24+
pub use utils::*;
25+
2326
#[cfg(windows)]
2427
pub mod named_pipe;
2528

compio-fs/src/utils/mod.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#[cfg(unix)]
2+
#[path = "unix.rs"]
3+
mod sys;
4+
5+
#[cfg(windows)]
6+
#[path = "windows.rs"]
7+
mod sys;
8+
9+
use std::{io, path::Path};
10+
11+
use compio_buf::{buf_try, BufResult, IoBuf};
12+
use compio_io::{AsyncReadAtExt, AsyncWriteAtExt};
13+
14+
use crate::{metadata, File};
15+
16+
/// Removes a file from the filesystem.
17+
pub async fn remove_file(path: impl AsRef<Path>) -> io::Result<()> {
18+
sys::remove_file(path).await
19+
}
20+
21+
/// Removes an empty directory.
22+
pub async fn remove_dir(path: impl AsRef<Path>) -> io::Result<()> {
23+
sys::remove_dir(path).await
24+
}
25+
26+
/// Creates a new, empty directory at the provided path.
27+
pub async fn create_dir(path: impl AsRef<Path>) -> io::Result<()> {
28+
DirBuilder::new().create(path).await
29+
}
30+
31+
/// Recursively create a directory and all of its parent components if they are
32+
/// missing.
33+
pub async fn create_dir_all(path: impl AsRef<Path>) -> io::Result<()> {
34+
DirBuilder::new().recursive(true).create(path).await
35+
}
36+
37+
/// Rename a file or directory to a new name, replacing the original file if
38+
/// `to` already exists.
39+
pub async fn rename(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
40+
sys::rename(from, to).await
41+
}
42+
43+
/// Creates a new symbolic link on the filesystem.
44+
#[cfg(unix)]
45+
pub async fn symlink(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
46+
sys::symlink(original, link).await
47+
}
48+
49+
/// Creates a new symlink to a non-directory file on the filesystem.
50+
#[cfg(windows)]
51+
pub async fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
52+
sys::symlink_file(original, link).await
53+
}
54+
55+
/// Creates a new symlink to a directory on the filesystem.
56+
#[cfg(windows)]
57+
pub async fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
58+
sys::symlink_dir(original, link).await
59+
}
60+
61+
/// Creates a new hard link on the filesystem.
62+
pub async fn hard_link(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
63+
sys::hard_link(original, link).await
64+
}
65+
66+
/// Write a slice as the entire contents of a file.
67+
///
68+
/// This function will create a file if it does not exist,
69+
/// and will entirely replace its contents if it does.
70+
pub async fn write<P: AsRef<Path>, B: IoBuf>(path: P, buf: B) -> BufResult<(), B> {
71+
let (mut file, buf) = buf_try!(File::create(path).await, buf);
72+
file.write_all_at(buf, 0).await
73+
}
74+
75+
/// Read the entire contents of a file into a bytes vector.
76+
pub async fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
77+
let file = File::open(path).await?;
78+
let BufResult(res, buffer) = file.read_to_end_at(Vec::new(), 0).await;
79+
res?;
80+
Ok(buffer)
81+
}
82+
83+
/// A builder used to create directories in various manners.
84+
pub struct DirBuilder {
85+
inner: sys::DirBuilder,
86+
recursive: bool,
87+
}
88+
89+
impl Default for DirBuilder {
90+
fn default() -> Self {
91+
Self::new()
92+
}
93+
}
94+
95+
impl DirBuilder {
96+
/// Creates a new set of options with default mode/security settings for all
97+
/// platforms and also non-recursive.
98+
pub fn new() -> Self {
99+
Self {
100+
inner: sys::DirBuilder::new(),
101+
recursive: false,
102+
}
103+
}
104+
105+
/// Indicates that directories should be created recursively, creating all
106+
/// parent directories. Parents that do not exist are created with the same
107+
/// security and permissions settings.
108+
pub fn recursive(&mut self, recursive: bool) -> &mut Self {
109+
self.recursive = recursive;
110+
self
111+
}
112+
113+
/// Creates the specified directory with the options configured in this
114+
/// builder.
115+
pub async fn create(&self, path: impl AsRef<Path>) -> io::Result<()> {
116+
let path = path.as_ref();
117+
if self.recursive {
118+
self.create_dir_all(path).await
119+
} else {
120+
self.inner.create(path).await
121+
}
122+
}
123+
124+
async fn create_dir_all(&self, path: &Path) -> io::Result<()> {
125+
if path == Path::new("") {
126+
return Ok(());
127+
}
128+
129+
match self.inner.create(path).await {
130+
Ok(()) => return Ok(()),
131+
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
132+
Err(_) if metadata(path).await.map(|m| m.is_dir()).unwrap_or_default() => return Ok(()),
133+
Err(e) => return Err(e),
134+
}
135+
match path.parent() {
136+
Some(p) => Box::pin(self.create_dir_all(p)).await?,
137+
None => {
138+
return Err(io::Error::new(
139+
io::ErrorKind::Other,
140+
"failed to create whole tree",
141+
));
142+
}
143+
}
144+
match self.inner.create(path).await {
145+
Ok(()) => Ok(()),
146+
Err(_) if metadata(path).await.map(|m| m.is_dir()).unwrap_or_default() => Ok(()),
147+
Err(e) => Err(e),
148+
}
149+
}
150+
}
151+
152+
#[cfg(unix)]
153+
impl std::os::unix::fs::DirBuilderExt for DirBuilder {
154+
fn mode(&mut self, mode: u32) -> &mut Self {
155+
self.inner.mode(mode);
156+
self
157+
}
158+
}

0 commit comments

Comments
 (0)