From 63ff5858df58ec41bafa31047085d35f6a2be4c2 Mon Sep 17 00:00:00 2001 From: Xu Shaohua Date: Fri, 18 Oct 2024 04:59:30 +0800 Subject: [PATCH] linux: Fix type of d_name error in linux_dirent_t Issue: https://github.com/XuShaohua/nc/issues/37 --- src/c_str.rs | 3 +- src/platform/linux-types/fs/fs_readdir.rs | 35 ++++++----------------- src/platform/linux-types/linux/dirent.rs | 19 +++--------- 3 files changed, 15 insertions(+), 42 deletions(-) diff --git a/src/c_str.rs b/src/c_str.rs index a5526be9..a8f2fb1e 100644 --- a/src/c_str.rs +++ b/src/c_str.rs @@ -25,8 +25,9 @@ use core::ptr; /// ``` #[must_use] pub fn strlen(buf: usize, len: usize) -> usize { + let buf_ptr = buf as *const u8; for i in 0..len { - let chr: u8 = unsafe { *((buf + i) as *const u8) }; + let chr: u8 = unsafe { *buf_ptr.wrapping_add(i) }; if chr == 0 { return i; } diff --git a/src/platform/linux-types/fs/fs_readdir.rs b/src/platform/linux-types/fs/fs_readdir.rs index 42fda51f..51391113 100644 --- a/src/platform/linux-types/fs/fs_readdir.rs +++ b/src/platform/linux-types/fs/fs_readdir.rs @@ -4,11 +4,13 @@ //! From `fs/readir.c` -use core::{fmt, mem, ptr, slice}; +use core::{fmt, ptr, slice}; -use crate::{ino64_t, loff_t, PATH_MAX}; +use crate::c_str::strlen; +use crate::{ino64_t, loff_t, DT_UNKNOWN, PATH_MAX}; #[repr(C)] +#[derive(Default)] pub struct linux_dirent_t { /// Inode number pub d_ino: ino64_t, @@ -20,18 +22,7 @@ pub struct linux_dirent_t { pub d_reclen: u16, /// Filename (null-terminated) - pub d_name: *mut u8, -} - -impl Default for linux_dirent_t { - fn default() -> Self { - Self { - d_ino: 0, - d_off: 0, - d_reclen: 0, - d_name: core::ptr::null_mut(), - } - } + pub d_name: [u8; 0], } impl linux_dirent_t { @@ -48,21 +39,13 @@ impl linux_dirent_t { unsafe { d_type_ptr.read() } } - #[must_use] - #[inline] - pub const fn name_max_len(&self) -> usize { - // FIXME(Shaohua): offset_of d_name is different from linux_dirent in C, which is 18. - // Also `repr(packed)` is ok, which makes it harder to use this struct. - //self.d_reclen as usize - 2 - mem::offset_of!(Self, d_name) - self.d_reclen as usize - 2 - mem::offset_of!(Self, d_reclen) - 2 - } - + /// Get inner `CString` #[must_use] #[inline] pub fn name(&self) -> &[u8] { - let max_len = self.name_max_len(); - let d_name_ptr: *const u8 = ptr::addr_of!(self.d_reclen).cast::().wrapping_add(2); - unsafe { slice::from_raw_parts(d_name_ptr, max_len) } + let d_name_ptr: *const u8 = ptr::addr_of!(self.d_name).cast::(); + let name_len = strlen(d_name_ptr as usize, self.d_reclen as usize); + unsafe { slice::from_raw_parts(d_name_ptr, name_len) } } } diff --git a/src/platform/linux-types/linux/dirent.rs b/src/platform/linux-types/linux/dirent.rs index 4b22c207..b851a6c6 100644 --- a/src/platform/linux-types/linux/dirent.rs +++ b/src/platform/linux-types/linux/dirent.rs @@ -6,8 +6,9 @@ #![allow(clippy::module_name_repetitions)] -use core::{fmt, mem, slice}; +use core::{fmt, ptr, slice}; +use crate::c_str::strlen; use crate::{ino64_t, loff_t}; const NAME_MAX_LEN: usize = 256; @@ -43,26 +44,14 @@ impl Default for linux_dirent64_t { } impl linux_dirent64_t { - /// `d_name` may be smaller than this length value. - #[must_use] - #[inline] - pub const fn name_max_len(&self) -> usize { - self.d_reclen as usize - mem::offset_of!(Self, d_name) - } - /// Return filename. /// /// name does not contain null-termination. #[must_use] #[inline] pub fn name(&self) -> &[u8] { - let max_len = self.name_max_len(); - for i in 0..max_len { - if self.d_name[i] == b'\0' { - return &self.d_name[..i]; - } - } - &self.d_name[..max_len] + let name_len = strlen(self.d_name.as_ptr() as usize, self.d_reclen as usize); + &self.d_name[..name_len] } }