posix_invariant_checker/fs/
mkdir.rs1use std::{ffi::CString, os::unix::prelude::OsStrExt};
2
3use crate::{
4 fs::{chdirin, chdirout, restore_ids, set_ids, stat_path, TTL},
5 fs_to_fuse::FsToFuseAttr,
6 invariants::fs::mkdir::{inv_mkdir_after, inv_mkdir_before},
7 log_call, log_more, log_res,
8};
9
10use super::InvFS;
11
12impl InvFS {
13 pub fn do_mkdir(
14 &mut self,
15 req: &fuser::Request<'_>,
16 parent: u64,
17 name: &std::ffi::OsStr,
18 mode: u32,
19 umask: u32,
20 reply: fuser::ReplyEntry,
21 ) {
22 let callid = log_call!(
23 "MKDIR",
24 "parent={},name={:?},mode={:o},umask={:o}",
25 parent,
26 name,
27 mode,
28 umask
29 );
30 let cwd = chdirin(&self.root);
31 let mut dl = self.data.lock().unwrap();
32 let inv = inv_mkdir_before(callid, req, &self.root, parent, name, mode, umask, &mut dl);
33 let ids = set_ids(callid, req, Some(umask));
34 let ip = &mut dl.INODE_PATHS;
35 let p_path = ip.get(parent);
36 log_more!(callid, "parent={:?}", p_path);
37 let child = p_path.join(name);
38 log_more!(callid, "child={:?}", child);
39 let res = unsafe {
40 let tgt = CString::new(child.as_os_str().as_bytes()).unwrap();
41 let res = libc::mkdir(tgt.as_ptr(), mode);
42 if res == 0 {
43 stat_path(&child).map(|x| {
44 let ino = ip.insert(x.st_ino, child);
45 x.to_fuse_attr(ino)
46 })
47 } else {
48 Err(*libc::__errno_location())
49 }
50 };
51 log_res!(callid, "{:?}", res);
52 restore_ids(ids);
53 inv_mkdir_after(callid, inv, &res, &mut dl);
54 chdirout(cwd);
55 match res {
56 Ok(v) => reply.entry(&TTL, &v, 0),
57 Err(v) => reply.error(v),
58 }
59 }
60}