posix_invariant_checker/fs/
mkdir.rs

1use 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}