-
Notifications
You must be signed in to change notification settings - Fork 7
Add functions to get original file name and loop device info #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -38,8 +38,9 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //! ld.detach().unwrap(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //! ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use crate::bindings::{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loop_info64, LOOP_CLR_FD, LOOP_CTL_ADD, LOOP_CTL_GET_FREE, LOOP_SET_CAPACITY, LOOP_SET_FD, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LOOP_SET_STATUS64, LO_FLAGS_AUTOCLEAR, LO_FLAGS_PARTSCAN, LO_FLAGS_READ_ONLY, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loop_info64, LOOP_CLR_FD, LOOP_CTL_ADD, LOOP_CTL_GET_FREE, LOOP_GET_STATUS64, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LOOP_SET_CAPACITY, LOOP_SET_FD, LOOP_SET_STATUS64, LO_FLAGS_AUTOCLEAR, LO_FLAGS_PARTSCAN, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LO_FLAGS_READ_ONLY, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(feature = "direct_io")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use bindings::LOOP_SET_DIRECT_IO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -52,13 +53,17 @@ use std::{ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path::{Path, PathBuf}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use loname::Name; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[allow(non_camel_case_types)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[allow(dead_code)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[allow(non_snake_case)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mod bindings { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include!(concat!(env!("OUT_DIR"), "/bindings.rs")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mod loname; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(all(not(target_os = "android"), not(target_env = "musl")))] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type IoctlRequest = libc::c_ulong; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(any(target_os = "android", target_env = "musl"))] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -243,9 +248,15 @@ impl LoopDevice { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn attach_with_loop_info( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &self, // TODO should be mut? - but changing it is a breaking change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backing_file: impl AsRef<Path>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| info: loop_info64, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mut info: loop_info64, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> io::Result<()> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let write_access = (info.lo_flags & LO_FLAGS_READ_ONLY) == 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // store backing file name in the info | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let name = loname::Name::from_path(&backing_file).unwrap_or_default(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| info.lo_file_name = name.0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| info.lo_crypt_name = name.0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would you consider only setting
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't use |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let bf = OpenOptions::new() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .read(true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .write(write_access) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -312,6 +323,23 @@ impl LoopDevice { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::fs::read_link(&p).ok() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Try to obtain the original file path used on mapping | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// The method ignores ioctl errors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// The path expected to be stored in the loop_info64. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// If it's not there, method returns None, otherwise - the string stored | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn original_path(&self) -> Option<PathBuf> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.info().ok().and_then(|info| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let name = Name(info.lo_file_name).to_string(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if name.is_empty() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Some(PathBuf::from(name)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+326
to
+341
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lossless original_path: build PathBuf from raw bytes, not a UTF‑8 String Current code can mangle non‑UTF‑8 paths. Use the bytes up to the first NUL and construct an OsString via OsStringExt. Apply this diff: - pub fn original_path(&self) -> Option<PathBuf> {
- self.info().ok().and_then(|info| {
- let name = Name(info.lo_file_name).to_string();
- if name.is_empty() {
- None
- } else {
- Some(PathBuf::from(name))
- }
- })
- }
+ pub fn original_path(&self) -> Option<PathBuf> {
+ self.info().ok().and_then(|info| {
+ let raw = &info.lo_file_name;
+ let end = raw.iter().position(|&b| b == 0).unwrap_or(raw.len());
+ if end == 0 {
+ None
+ } else {
+ Some(PathBuf::from(
+ std::os::unix::ffi::OsStringExt::from_vec(raw[..end].to_vec()),
+ ))
+ }
+ })
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Get the device major number | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Errors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -390,6 +418,21 @@ impl LoopDevice { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Obtain loop_info64 struct for the loop device | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Ok(loop_info64) - successfully obtained info | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Err(std::io::Error) - error from ioctl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn info(&self) -> Result<loop_info64, std::io::Error> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let empty_info = Box::new(loop_info64::default()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let fd = self.device.as_raw_fd(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unsafe { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let ptr = Box::into_raw(empty_info); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let ret_code = libc::ioctl(fd.as_raw_fd(), LOOP_GET_STATUS64 as IoctlRequest, ptr); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ioctl_to_error(ret_code).map(|_| *Box::from_raw(ptr)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+421
to
+435
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix memory leak and invalid fd usage in info()
Apply this diff: - pub fn info(&self) -> Result<loop_info64, std::io::Error> {
- let empty_info = Box::new(loop_info64::default());
- let fd = self.device.as_raw_fd();
-
- unsafe {
- let ptr = Box::into_raw(empty_info);
- let ret_code = libc::ioctl(fd.as_raw_fd(), LOOP_GET_STATUS64 as IoctlRequest, ptr);
- ioctl_to_error(ret_code).map(|_| *Box::from_raw(ptr))
- }
- }
+ pub fn info(&self) -> Result<loop_info64, std::io::Error> {
+ let mut info = loop_info64::default();
+ let ret = unsafe {
+ libc::ioctl(
+ self.device.as_raw_fd() as c_int,
+ LOOP_GET_STATUS64 as IoctlRequest,
+ &mut info,
+ )
+ };
+ ioctl_to_error(ret).map(|_| info)
+ }🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Enable or disable direct I/O for the backing file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Errors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,88 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //! Configuration structures for loop device | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::path::Path; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use crate::bindings::LO_NAME_SIZE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Loop device name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[repr(C)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub struct Name(pub [libc::__u8; LO_NAME_SIZE as usize]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Allow to construct the config easily | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl Default for Name { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn default() -> Self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Self([0; LO_NAME_SIZE as usize]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Conversions simplifiers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl Name { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn from_path<Y: AsRef<Path>>(path: Y) -> Result<Self, String> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let s = path.as_ref().as_os_str().as_encoded_bytes(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if s.len() > LO_NAME_SIZE as usize { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm concerned that this use of
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(format!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "too many bytes in the provided loop dev source file path: {}, max {LO_NAME_SIZE}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s.len() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut data: [u8; 64] = [0; LO_NAME_SIZE as usize]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (idx, byte) in s.iter().enumerate() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data[idx] = *byte; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(Self(data)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+29
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid hard-coding 64; use LO_NAME_SIZE and copy_from_slice Hard-coding the array length risks mismatch if LO_NAME_SIZE changes. Also, use copy_from_slice for clarity and bounds safety (you already guard len). Apply this diff: - let mut data: [u8; 64] = [0; LO_NAME_SIZE as usize];
- for (idx, byte) in s.iter().enumerate() {
- data[idx] = *byte;
- }
+ let mut data = [0u8; LO_NAME_SIZE as usize];
+ data[..s.len()].copy_from_slice(s);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[allow(clippy::to_string_trait_impl)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl ToString for Name { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn to_string(&self) -> String { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .iter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .filter_map(|ch| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let ch: char = *ch as char; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ch == '\0' { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Some(ch) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .collect::<String>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+37
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. String conversion is lossy for non‑UTF‑8 paths; switch to Display and expose raw bytes Casting each u8 to char and collecting into a String changes the byte sequence for values >= 0x80, breaking round‑trips for non‑UTF‑8 paths. Implement Display for human output and expose a bytes view for exact reconstruction. Apply this diff: -#[allow(clippy::to_string_trait_impl)]
-impl ToString for Name {
- fn to_string(&self) -> String {
- self.0
- .iter()
- .filter_map(|ch| {
- let ch: char = *ch as char;
- if ch == '\0' {
- None
- } else {
- Some(ch)
- }
- })
- .collect::<String>()
- }
-}
+impl std::fmt::Display for Name {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let end = self.0.iter().position(|&b| b == 0).unwrap_or(self.0.len());
+ let s = String::from_utf8_lossy(&self.0[..end]);
+ f.write_str(&s)
+ }
+}And add a bytes accessor to enable lossless OS string construction: impl Name {
pub fn from_path<Y: AsRef<Path>>(path: Y) -> Result<Self, String> {
let s = path.as_ref().as_os_str().as_encoded_bytes();
if s.len() > LO_NAME_SIZE as usize {
return Err(format!(
"too many bytes in the provided loop dev source file path: {}, max {LO_NAME_SIZE}",
s.len()
));
}
let mut data = [0u8; LO_NAME_SIZE as usize];
data[..s.len()].copy_from_slice(s);
Ok(Self(data))
}
+
+ /// Bytes up to the first NUL terminator.
+ pub fn as_bytes(&self) -> &[u8] {
+ let end = self.0.iter().position(|&b| b == 0).unwrap_or(self.0.len());
+ &self.0[..end]
+ }
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(test)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mod test { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::path::PathBuf; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use super::Name; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn test_name_empty() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let name = Name::default(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for num in name.0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!(0, num); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn test_name_from_to() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let path_string = "/a/b/some-file/cool name"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let path = PathBuf::from(&path_string); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let name = Name::from_path(path); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!(path_string, name.unwrap().to_string()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn test_name_too_long() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let path_string = "/too-long/too-long/too-long/too-long/too-long/too-long/too-long--"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let path = PathBuf::from(&path_string); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let name = Name::from_path(path); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "too many bytes in the provided loop dev source file path: 65, max 64", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name.unwrap_err() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the purpose of this but I'm unsure why you need the special Name struct for marshalling and unmarshalling. I feel that it would be better to use existing Path and PathBuf methods,
as_os_str()or something. Can you tell me why the concern w/ null terminators in theto_stringmethod? Thanks.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern was compatibility with C code.
I found that kernel actually takes care of the terminator here.
I did a brief check that name setup through
as_os_stris correctly displayed bylosetup -l, but that's not a reliable source, because ...losetup actually leverages
cat /sys/block/loop0/loop/backing_fileon my system. It isn't limited at 64 chars and a way more straight-forward path.I think I need to get rid of
lo_file_namelogic but keepinfoaround for future use.Do you think it's reasonable ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting the full name from
/sys/block/loop0/loop/backing_fileisn't that simple, as it requires to know theloop0part, which, in its turn, requires aninfocall. The only real advantage is that it allows to get the full name in all cases.LMK if you want to see the version with
as_os_stranyways