in src/nodes/dir.rs [639:682]
fn mknod(&self, name: &OsStr, uid: unistd::Uid, gid: unistd::Gid, mode: u32, rdev: u32,
ids: &IdGenerator, cache: &dyn Cache) -> NodeResult<(ArcNode, fuse::FileAttr)> {
let mut state = self.state.lock().unwrap();
let path = Dir::get_writable_path(&mut state, name)?;
if mode > u32::from(std::u16::MAX) {
warn!("mknod got too-big mode {} (exceeds {})", mode, std::u16::MAX);
}
let mode = mode as sys::stat::mode_t;
// We have to break apart the incoming mode into a separate file type flag and a permissions
// set... only to have mknod() combine them later once again. Doesn't make a lot of sense
// but that the API we get from nix, hence ensure we are doing the right thing.
let (sflag, perm) = {
let sflag = sys::stat::SFlag::from_bits_truncate(mode);
let perm = sys::stat::Mode::from_bits_truncate(mode);
let truncated_mode = sflag.bits() | perm.bits();
if truncated_mode != mode {
warn!("mknod cannot only handle {} from mode {}", truncated_mode, mode);
}
(sflag, perm)
};
let exp_filetype = match sflag {
sys::stat::SFlag::S_IFBLK => fuse::FileType::BlockDevice,
sys::stat::SFlag::S_IFCHR => fuse::FileType::CharDevice,
sys::stat::SFlag::S_IFIFO => fuse::FileType::NamedPipe,
sys::stat::SFlag::S_IFREG => fuse::FileType::RegularFile,
_ => {
warn!("mknod received request to create {} with type {:?}, which is not supported",
path.display(), sflag);
return Err(KernelError::from_errno(errno::Errno::EIO));
},
};
#[allow(clippy::cast_lossless)]
create_as(
&path, uid, gid,
|p| sys::stat::mknod(p, sflag, perm, rdev as sys::stat::dev_t),
|p| unistd::unlink(p))?;
Dir::post_create_lookup(self.writable, &mut state, &path, name, exp_filetype, ids, cache)
}