From a9227257f609c8ba63563b793d961a055ab84261 Mon Sep 17 00:00:00 2001 From: Khanh Tran Date: Tue, 3 Mar 2026 14:28:07 +0700 Subject: [PATCH 1/2] fix: repair DeviceType enum in mknod to be hydrated from mode and rdev fields --- src/types/arguments.rs | 51 +++++++++++++++---------------------- src/unix_fs.rs | 21 ++++++++------- templates/fuse_driver.rs.j2 | 12 ++++++++- 3 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/types/arguments.rs b/src/types/arguments.rs index 0573c40..8df818d 100644 --- a/src/types/arguments.rs +++ b/src/types/arguments.rs @@ -19,7 +19,6 @@ use std::time::{Duration, SystemTime}; use fuser::FileAttr as FuseFileAttr; use fuser::{FileType, Request, TimeOrNow}; -use libc::mode_t; use super::BorrowedFileHandle; use super::LockType; @@ -63,40 +62,30 @@ pub enum DeviceType { } impl DeviceType { - pub fn from_rdev(rdev: mode_t) -> Self { - use libc::*; - // Extract major and minor device numbers (assuming the device number format). - let major: u32 = (rdev >> 8).into(); // Major is the upper part of the 32-bit value (16 bit on macos) - let minor: u32 = (rdev & 0xFF).into(); // Minor is the lower 8 bits - match rdev { - x if x & S_IFREG != 0 => DeviceType::RegularFile, - x if x & S_IFDIR != 0 => DeviceType::Directory, - x if x & S_IFCHR != 0 => DeviceType::CharacterDevice { major, minor }, - x if x & S_IFBLK != 0 => DeviceType::BlockDevice { major, minor }, - x if x & S_IFIFO != 0 => DeviceType::NamedPipe, - x if x & S_IFSOCK != 0 => DeviceType::Socket, - x if x & S_IFLNK != 0 => DeviceType::Symlink, - _ => DeviceType::Unknown, + pub fn from_file_type_and_rdev(file_type: FileType, rdev: libc::dev_t) -> Self { + let major: u32 = libc::major(rdev); + let minor: u32 = libc::minor(rdev); + + match file_type { + FileType::RegularFile => DeviceType::RegularFile, + FileType::Directory => DeviceType::Directory, + FileType::CharDevice => DeviceType::CharacterDevice { major, minor }, + FileType::BlockDevice => DeviceType::BlockDevice { major, minor }, + FileType::NamedPipe => DeviceType::NamedPipe, + FileType::Socket => DeviceType::Socket, + FileType::Symlink => DeviceType::Symlink, } } - pub fn to_rdev(&self) -> mode_t { - use libc::*; - + pub fn to_rdev(&self) -> libc::dev_t { match self { - DeviceType::RegularFile => S_IFREG, - DeviceType::Directory => S_IFDIR, - DeviceType::CharacterDevice { major, minor } => { - let device = ((major & 0xFF) << 8) | (minor & 0xFF); - (device as mode_t) | S_IFCHR - } - DeviceType::BlockDevice { major, minor } => { - let device = ((major & 0xFF) << 8) | (minor & 0xFF); - (device as mode_t) | S_IFBLK - } - DeviceType::NamedPipe => S_IFIFO, - DeviceType::Socket => S_IFSOCK, - DeviceType::Symlink => S_IFLNK, + DeviceType::RegularFile => 0, + DeviceType::Directory => 0, + DeviceType::CharacterDevice { major, minor } => libc::makedev(*major, *minor), + DeviceType::BlockDevice { major, minor } => libc::makedev(*major, *minor), + DeviceType::NamedPipe => 0, + DeviceType::Socket => 0, + DeviceType::Symlink => 0, DeviceType::Unknown => 0, // Represents an unknown device } } diff --git a/src/unix_fs.rs b/src/unix_fs.rs index 2d0b8a8..8e6b4d3 100644 --- a/src/unix_fs.rs +++ b/src/unix_fs.rs @@ -132,7 +132,7 @@ fn convert_stat_struct(statbuf: libc::stat) -> Option { mtime, ctime, crtime: mtime, - kind: stat_to_kind(statbuf)?, + kind: mode_to_kind(statbuf.st_mode)?, perm: perm, nlink: statbuf.st_nlink as u32, uid: statbuf.st_uid as u32, @@ -145,16 +145,15 @@ fn convert_stat_struct(statbuf: libc::stat) -> Option { }) } -fn stat_to_kind(statbuf: libc::stat) -> Option { - use libc::*; - Some(match statbuf.st_mode & S_IFMT { - S_IFREG => FileKind::RegularFile, - S_IFDIR => FileKind::Directory, - S_IFCHR => FileKind::CharDevice, - S_IFBLK => FileKind::BlockDevice, - S_IFIFO => FileKind::NamedPipe, - S_IFLNK => FileKind::Symlink, - S_IFSOCK => FileKind::Socket, +pub(crate) fn mode_to_kind(mode: u32) -> Option { + Some(match mode & libc::S_IFMT { + libc::S_IFREG => FileKind::RegularFile, + libc::S_IFDIR => FileKind::Directory, + libc::S_IFCHR => FileKind::CharDevice, + libc::S_IFBLK => FileKind::BlockDevice, + libc::S_IFIFO => FileKind::NamedPipe, + libc::S_IFLNK => FileKind::Symlink, + libc::S_IFSOCK => FileKind::Socket, _ => return None, // Unsupported or unknown file type }) } diff --git a/templates/fuse_driver.rs.j2 b/templates/fuse_driver.rs.j2 index bc811bb..a2d5cc2 100644 --- a/templates/fuse_driver.rs.j2 +++ b/templates/fuse_driver.rs.j2 @@ -17,6 +17,7 @@ use fuser::{ ReplyStatfs, ReplyWrite, ReplyXattr, Request, TimeOrNow, }; +use crate::unix_fs; use crate::fuse_handler::FuseHandler; use crate::types::*; use crate::core::helpers::*; @@ -708,13 +709,22 @@ where let resolver = self.resolver.clone(); let name = name.to_owned(); {% call spawn() %} + let file_kind = match unix_fs::mode_to_kind(mode) { + Some(file_kind) => file_kind, + None => { + {% call spawn_reply() %} + reply.error(ErrorKind::InvalidArgument.into()); + {% endcall %} + return; + } + }; match handler.mknod( &req, resolver.resolve_id(parent), &name, mode, umask, - DeviceType::from_rdev(rdev.try_into().unwrap()) + DeviceType::from_file_type_and_rdev(file_kind, rdev.try_into().unwrap()) ) { {% call reply_entry("parent", "name") %}{% endcall %} Err(e) => { From 5ff83fde651e8d2f24510ba60c0f5a553179808f Mon Sep 17 00:00:00 2001 From: Khanh Tran Date: Tue, 3 Mar 2026 14:51:24 +0700 Subject: [PATCH 2/2] fix: add compatibility into() stub for future fuser APIs --- src/types/errors.rs | 6 ++++++ templates/fuse_driver.rs.j2 | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/types/errors.rs b/src/types/errors.rs index 897a870..13622ad 100644 --- a/src/types/errors.rs +++ b/src/types/errors.rs @@ -383,6 +383,12 @@ impl From for i32 { } } +impl Into for PosixError { + fn into(self) -> i32 { + self.code + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/templates/fuse_driver.rs.j2 b/templates/fuse_driver.rs.j2 index a2d5cc2..57bcfef 100644 --- a/templates/fuse_driver.rs.j2 +++ b/templates/fuse_driver.rs.j2 @@ -713,7 +713,7 @@ where Some(file_kind) => file_kind, None => { {% call spawn_reply() %} - reply.error(ErrorKind::InvalidArgument.into()); + reply.error(PosixError::new(ErrorKind::InvalidArgument, "unknown file kind").into()); {% endcall %} return; }