diff --git a/native/src/base/cstr.rs b/native/src/base/cstr.rs index acb415392..ab9f9ab31 100644 --- a/native/src/base/cstr.rs +++ b/native/src/base/cstr.rs @@ -10,6 +10,27 @@ use crate::slice_from_ptr_mut; use libc::c_char; use thiserror::Error; +// Utf8CStr types are UTF-8 validated and null terminated strings. +// +// Several Utf8CStr types: +// +// Utf8CStr: can only exist as reference, similar to &str +// Utf8CString: dynamically sized buffer allocated on the heap +// Utf8CStrBufRef: reference to a fixed sized buffer +// Utf8CStrBufArr: fixed sized buffer allocated on the stack +// +// In most cases, these are the types being used +// +// &Utf8CStr: whenever a printable null terminated string is needed +// &mut dyn Utf8CStrWrite: whenever we need a buffer that only needs to support appending +// strings to the end, and has to be null terminated +// &mut dyn Utf8CStrBuf: whenever we need a pre-allocated buffer that is large enough to fit +// in the result, and has to be null terminated +// +// All types dereferences to &Utf8CStr. +// Utf8CString, Utf8CStrBufRef, and Utf8CStrBufArr implements Utf8CStrWrite. +// Utf8CStrBufRef and Utf8CStrBufArr implements Utf8CStrBuf. + pub fn copy_cstr + ?Sized>(dest: &mut [u8], src: &T) -> usize { let src = src.as_ref().to_bytes_with_nul(); let len = min(src.len(), dest.len()); @@ -17,7 +38,7 @@ pub fn copy_cstr + ?Sized>(dest: &mut [u8], src: &T) -> usize { len - 1 } -fn utf8_cstr_append(buf: &mut dyn Utf8CStrBuf, s: &[u8]) -> usize { +fn utf8_cstr_buf_append(buf: &mut dyn Utf8CStrBuf, s: &[u8]) -> usize { let mut used = buf.len(); if used >= buf.capacity() - 1 { // Truncate @@ -32,28 +53,35 @@ fn utf8_cstr_append(buf: &mut dyn Utf8CStrBuf, s: &[u8]) -> usize { len } -fn utf8_cstr_append_lossy(buf: &mut dyn Utf8CStrBuf, s: &[u8]) -> usize { +fn utf8_cstr_append_lossy(buf: &mut dyn Utf8CStrWrite, s: &[u8]) -> usize { let chunks = Utf8Chunks::new(s); let mut len = 0_usize; for chunk in chunks { - len += utf8_cstr_append(buf, chunk.valid().as_bytes()); + len += buf.push_str(chunk.valid()); if !chunk.invalid().is_empty() { - len += utf8_cstr_append( - buf, - char::REPLACEMENT_CHARACTER - .encode_utf8(&mut [0; 4]) - .as_bytes(), - ); + len += buf.push_str(char::REPLACEMENT_CHARACTER.encode_utf8(&mut [0; 4])); } } len } -pub trait Utf8CStrBuf: +// Trait definitions + +pub trait Utf8CStrWrite: Write + AsRef + AsMut + Deref + DerefMut { - fn buf(&self) -> &[u8]; fn len(&self) -> usize; + #[inline(always)] + fn is_empty(&self) -> bool { + self.len() == 0 + } + fn push_str(&mut self, s: &str) -> usize; + fn push_lossy(&mut self, s: &[u8]) -> usize; + fn clear(&mut self); +} + +pub trait Utf8CStrBuf: Utf8CStrWrite { + fn buf(&self) -> &[u8]; // Modifying the underlying buffer or length is unsafe because it can either: // 1. Break null termination @@ -62,29 +90,92 @@ pub trait Utf8CStrBuf: unsafe fn mut_buf(&mut self) -> &mut [u8]; unsafe fn set_len(&mut self, len: usize); - fn append(&mut self, s: &str) -> usize; - fn append_lossy(&mut self, s: &[u8]) -> usize; - unsafe fn append_unchecked(&mut self, s: &[u8]) -> usize; - - #[inline(always)] - fn is_empty(&self) -> bool { - self.len() == 0 - } - #[inline(always)] fn capacity(&self) -> usize { self.buf().len() } +} - fn clear(&mut self) { +trait AsUtf8CStr { + fn as_utf8_cstr(&self) -> &Utf8CStr; + fn as_utf8_cstr_mut(&mut self) -> &mut Utf8CStr; +} + +// Implementation for Utf8CString + +trait StringExt { + fn nul_terminate(&mut self) -> &mut [u8]; +} + +impl StringExt for String { + fn nul_terminate(&mut self) -> &mut [u8] { + self.reserve(1); + // SAFETY: the string is reserved to have enough capacity to fit in the null byte + // SAFETY: the null byte is explicitly added outside of the string's length unsafe { - self.mut_buf()[0] = b'\0'; - self.set_len(0); + let buf = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len() + 1); + *buf.get_unchecked_mut(self.len()) = b'\0'; + buf } } } -trait Utf8CStrBufImpl: Utf8CStrBuf { +#[derive(Default)] +pub struct Utf8CString(String); + +impl Utf8CString { + #[inline(always)] + pub fn new() -> Self { + Self::default() + } +} + +impl AsUtf8CStr for Utf8CString { + #[inline(always)] + fn as_utf8_cstr(&self) -> &Utf8CStr { + // SAFETY: the internal string is always null terminated + unsafe { mem::transmute(slice::from_raw_parts(self.0.as_ptr(), self.0.len() + 1)) } + } + + #[inline(always)] + fn as_utf8_cstr_mut(&mut self) -> &mut Utf8CStr { + Utf8CStr::from_string(&mut self.0) + } +} + +impl Utf8CStrWrite for Utf8CString { + #[inline(always)] + fn len(&self) -> usize { + self.0.len() + } + + fn push_str(&mut self, s: &str) -> usize { + self.0.push_str(s); + self.0.nul_terminate(); + s.len() + } + + #[inline(always)] + fn push_lossy(&mut self, s: &[u8]) -> usize { + utf8_cstr_append_lossy(self, s) + } + + fn clear(&mut self) { + self.0.clear(); + self.0.nul_terminate(); + } +} + +impl From for Utf8CString { + fn from(mut value: String) -> Self { + value.nul_terminate(); + Utf8CString(value) + } +} + +// Implementations for Utf8CStrBuf + +impl AsUtf8CStr for T { #[inline(always)] fn as_utf8_cstr(&self) -> &Utf8CStr { // SAFETY: the internal buffer is always UTF-8 checked @@ -104,35 +195,30 @@ trait Utf8CStrBufImpl: Utf8CStrBuf { } // UTF-8 validated + null terminated reference to buffer -pub struct Utf8CStrSlice<'a> { +pub struct Utf8CStrBufRef<'a> { used: usize, buf: &'a mut [u8], } -impl<'a> Utf8CStrSlice<'a> { - pub unsafe fn from_ptr(buf: *mut u8, len: usize) -> Utf8CStrSlice<'a> { +impl<'a> Utf8CStrBufRef<'a> { + pub unsafe fn from_ptr(buf: *mut u8, len: usize) -> Utf8CStrBufRef<'a> { Self::from(slice_from_ptr_mut(buf, len)) } } -impl<'a> From<&'a mut [u8]> for Utf8CStrSlice<'a> { - fn from(buf: &'a mut [u8]) -> Utf8CStrSlice<'a> { +impl<'a> From<&'a mut [u8]> for Utf8CStrBufRef<'a> { + fn from(buf: &'a mut [u8]) -> Utf8CStrBufRef<'a> { buf[0] = b'\0'; - Utf8CStrSlice { used: 0, buf } + Utf8CStrBufRef { used: 0, buf } } } -impl Utf8CStrBuf for Utf8CStrSlice<'_> { +impl Utf8CStrBuf for Utf8CStrBufRef<'_> { #[inline(always)] fn buf(&self) -> &[u8] { self.buf } - #[inline(always)] - fn len(&self) -> usize { - self.used - } - #[inline(always)] unsafe fn mut_buf(&mut self) -> &mut [u8] { self.buf @@ -142,49 +228,29 @@ impl Utf8CStrBuf for Utf8CStrSlice<'_> { unsafe fn set_len(&mut self, len: usize) { self.used = len; } - - #[inline(always)] - fn append(&mut self, s: &str) -> usize { - utf8_cstr_append(self, s.as_bytes()) - } - - #[inline(always)] - fn append_lossy(&mut self, s: &[u8]) -> usize { - utf8_cstr_append_lossy(self, s) - } - - #[inline(always)] - unsafe fn append_unchecked(&mut self, s: &[u8]) -> usize { - utf8_cstr_append(self, s) - } } // UTF-8 validated + null terminated buffer on the stack -pub struct Utf8CStrArr { +pub struct Utf8CStrBufArr { used: usize, buf: [u8; N], } -impl Utf8CStrArr { +impl Utf8CStrBufArr { pub fn new() -> Self { - Utf8CStrArr { + Utf8CStrBufArr { used: 0, buf: [0; N], } } } -impl Utf8CStrBuf for Utf8CStrArr { +impl Utf8CStrBuf for Utf8CStrBufArr { #[inline(always)] fn buf(&self) -> &[u8] { &self.buf } - #[inline(always)] - fn len(&self) -> usize { - self.used - } - #[inline(always)] unsafe fn mut_buf(&mut self) -> &mut [u8] { &mut self.buf @@ -195,30 +261,15 @@ impl Utf8CStrBuf for Utf8CStrArr { self.used = len; } - #[inline(always)] - fn append(&mut self, s: &str) -> usize { - utf8_cstr_append(self, s.as_bytes()) - } - - #[inline(always)] - fn append_lossy(&mut self, s: &[u8]) -> usize { - utf8_cstr_append_lossy(self, s) - } - - #[inline(always)] - unsafe fn append_unchecked(&mut self, s: &[u8]) -> usize { - utf8_cstr_append(self, s) - } - #[inline(always)] fn capacity(&self) -> usize { N } } -impl Default for Utf8CStrArr<4096> { +impl Default for Utf8CStrBufArr<4096> { fn default() -> Self { - Utf8CStrArr::<4096>::new() + Utf8CStrBufArr::<4096>::new() } } @@ -232,24 +283,6 @@ pub enum StrErr { NullPointerError, } -// Provide a way to have a heap allocated, UTF-8 validated, and null terminated string -pub trait StringExt { - fn nul_terminate(&mut self) -> &mut [u8]; -} - -impl StringExt for String { - fn nul_terminate(&mut self) -> &mut [u8] { - self.reserve(1); - // SAFETY: the string is reserved to have enough capacity to fit in the null byte - // SAFETY: the null byte is explicitly added outside of the string's length - unsafe { - let buf = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len() + 1); - *buf.get_unchecked_mut(self.len()) = b'\0'; - buf - } - } -} - // UTF-8 validated + null terminated string slice pub struct Utf8CStr([u8]); @@ -378,28 +411,28 @@ impl DerefMut for FsPath { } } -pub struct FsPathBuf<'a>(&'a mut dyn Utf8CStrBuf); +pub struct FsPathBuf<'a>(&'a mut dyn Utf8CStrWrite); impl<'a> FsPathBuf<'a> { - pub fn new(value: &'a mut dyn Utf8CStrBuf) -> Self { + pub fn new(value: &'a mut dyn Utf8CStrWrite) -> Self { FsPathBuf(value) } pub fn join>(self, path: T) -> Self { - fn inner(buf: &mut dyn Utf8CStrBuf, path: &str) { + fn inner(buf: &mut dyn Utf8CStrWrite, path: &str) { if path.starts_with('/') { buf.clear(); } else { - buf.append("/"); + buf.push_str("/"); } - buf.append(path); + buf.push_str(path); } inner(self.0, path.as_ref()); self } pub fn join_fmt(self, name: T) -> Self { - fn inner(buf: &mut dyn Utf8CStrBuf, path: Arguments) { + fn inner(buf: &mut dyn Utf8CStrWrite, path: Arguments) { buf.write_fmt(path).ok(); } inner(self.0, format_args!("/{}", name)); @@ -504,22 +537,17 @@ impl_str!( (Utf8CStr,) (FsPath,) (FsPathBuf<'_>,) + (Utf8CStrBufRef<'_>,) + (Utf8CStrBufArr, const N: usize) + (Utf8CString,) ); -macro_rules! impl_str_buf { +macro_rules! impl_str_write { ($( ($t:ty, $($g:tt)*) )*) => {$( - impl_str!(($t, $($g)*)); - impl<$($g)*> $t { - #[inline(always)] - pub fn append>(&mut self, s: T) -> usize { - utf8_cstr_append(self, s.as_ref().as_bytes()) - } - } - impl<$($g)*> Utf8CStrBufImpl for $t {} impl<$($g)*> Write for $t { #[inline(always)] fn write_str(&mut self, s: &str) -> fmt::Result { - self.append(s); + self.push_str(s); Ok(()) } } @@ -546,9 +574,41 @@ macro_rules! impl_str_buf { )*} } +impl_str_write!( + (Utf8CStrBufRef<'_>,) + (Utf8CStrBufArr, const N: usize) + (Utf8CString,) +); + +macro_rules! impl_str_buf { + ($( ($t:ty, $($g:tt)*) )*) => {$( + impl<$($g)*> Utf8CStrWrite for $t { + #[inline(always)] + fn len(&self) -> usize { + self.used + } + #[inline(always)] + fn push_str(&mut self, s: &str) -> usize { + utf8_cstr_buf_append(self, s.as_bytes()) + } + #[inline(always)] + fn push_lossy(&mut self, s: &[u8]) -> usize { + utf8_cstr_append_lossy(self, s) + } + #[inline(always)] + fn clear(&mut self) { + unsafe { + self.mut_buf()[0] = b'\0'; + self.set_len(0); + } + } + } + )*} +} + impl_str_buf!( - (Utf8CStrSlice<'_>,) - (Utf8CStrArr, const N: usize) + (Utf8CStrBufRef<'_>,) + (Utf8CStrBufArr, const N: usize) ); // The cstr! macro is copied from https://github.com/bytecodealliance/rustix/blob/main/src/cstr.rs diff --git a/native/src/base/cxx_extern.rs b/native/src/base/cxx_extern.rs index 8678309a8..ec72e85a4 100644 --- a/native/src/base/cxx_extern.rs +++ b/native/src/base/cxx_extern.rs @@ -10,11 +10,11 @@ use libc::mode_t; use crate::logging::CxxResultExt; pub(crate) use crate::xwrap::*; use crate::{ - clone_attr, fclone_attr, fd_path, map_fd, map_file, Directory, FsPath, Utf8CStr, Utf8CStrSlice, + clone_attr, fclone_attr, fd_path, map_fd, map_file, Directory, FsPath, Utf8CStr, Utf8CStrBufRef, }; pub(crate) fn fd_path_for_cxx(fd: RawFd, buf: &mut [u8]) -> isize { - let mut buf = Utf8CStrSlice::from(buf); + let mut buf = Utf8CStrBufRef::from(buf); fd_path(fd, &mut buf) .log_cxx_with_msg(|w| w.write_str("fd_path failed")) .map_or(-1_isize, |_| buf.len() as isize) @@ -24,7 +24,7 @@ pub(crate) fn fd_path_for_cxx(fd: RawFd, buf: &mut [u8]) -> isize { unsafe extern "C" fn canonical_path(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { match Utf8CStr::from_ptr(path) { Ok(p) => { - let mut buf = Utf8CStrSlice::from_ptr(buf, bufsz); + let mut buf = Utf8CStrBufRef::from_ptr(buf, bufsz); FsPath::from(p) .realpath(&mut buf) .map_or(-1, |_| buf.len() as isize) diff --git a/native/src/base/files.rs b/native/src/base/files.rs index 37b51b1e6..253113e83 100644 --- a/native/src/base/files.rs +++ b/native/src/base/files.rs @@ -20,8 +20,8 @@ use num_traits::AsPrimitive; use crate::cxx_extern::readlinkat_for_cxx; use crate::{ - copy_cstr, cstr, errno, error, FsPath, FsPathBuf, LibcReturn, Utf8CStr, Utf8CStrArr, - Utf8CStrBuf, + copy_cstr, cstr, errno, error, FsPath, FsPathBuf, LibcReturn, Utf8CStr, Utf8CStrBuf, + Utf8CStrBufArr, }; pub fn __open_fd_impl(path: &Utf8CStr, flags: i32, mode: mode_t) -> io::Result { @@ -42,7 +42,7 @@ macro_rules! open_fd { } pub fn fd_path(fd: RawFd, buf: &mut dyn Utf8CStrBuf) -> io::Result<()> { - let mut arr = Utf8CStrArr::<40>::new(); + let mut arr = Utf8CStrBufArr::<40>::new(); let path = FsPathBuf::new(&mut arr).join("/proc/self/fd").join_fmt(fd); path.read_link(buf) } @@ -140,7 +140,7 @@ impl WriteExt for T { pub struct FileAttr { pub st: libc::stat, - pub con: Utf8CStrArr<128>, + pub con: Utf8CStrBufArr<128>, } const XATTR_NAME_SELINUX: &[u8] = b"security.selinux\0"; @@ -168,8 +168,8 @@ impl DirEntry<'_> { pub fn path(&self, buf: &mut dyn Utf8CStrBuf) -> io::Result<()> { self.dir.path(buf)?; - buf.append("/"); - buf.append_lossy(self.d_name().to_bytes()); + buf.push_str("/"); + buf.push_lossy(self.d_name().to_bytes()); Ok(()) } @@ -227,13 +227,13 @@ impl DirEntry<'_> { } pub fn get_attr(&self) -> io::Result { - let mut path = Utf8CStrArr::default(); + let mut path = Utf8CStrBufArr::default(); self.path(&mut path)?; FsPath::from(path).get_attr() } pub fn set_attr(&self, attr: &FileAttr) -> io::Result<()> { - let mut path = Utf8CStrArr::default(); + let mut path = Utf8CStrBufArr::default(); self.path(&mut path)?; FsPath::from(path).set_attr(attr) } @@ -367,7 +367,7 @@ impl Directory { std::io::copy(&mut src, &mut dest)?; fd_set_attr(dest.as_raw_fd(), &attr)?; } else if e.is_lnk() { - let mut path = Utf8CStrArr::default(); + let mut path = Utf8CStrBufArr::default(); e.read_link(&mut path)?; unsafe { libc::symlinkat(path.as_ptr(), dir.as_raw_fd(), e.d_name.as_ptr()) @@ -629,7 +629,7 @@ impl FsPath { unsafe { attr = FileAttr { st: mem::zeroed(), - con: Utf8CStrArr::new(), + con: Utf8CStrBufArr::new(), }; libc::lstat(self.as_ptr(), &mut attr.st).as_os_err()?; if SELINUX_ENABLED.load(Ordering::Relaxed) { @@ -681,7 +681,7 @@ impl FsPath { let mut dest = path.create(O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0o777)?; std::io::copy(&mut src, &mut dest)?; } else if (attr.st.st_mode & libc::S_IFMT as c_uint) == S_IFLNK.as_() { - let mut buf = Utf8CStrArr::default(); + let mut buf = Utf8CStrBufArr::default(); self.read_link(&mut buf)?; unsafe { libc::symlink(buf.as_ptr(), path.as_ptr()).as_os_err()?; @@ -725,7 +725,7 @@ pub fn fd_get_attr(fd: RawFd) -> io::Result { unsafe { attr = FileAttr { st: mem::zeroed(), - con: Utf8CStrArr::new(), + con: Utf8CStrBufArr::new(), }; libc::fstat(fd, &mut attr.st).as_os_err()?; if SELINUX_ENABLED.load(Ordering::Relaxed) { diff --git a/native/src/base/logging.rs b/native/src/base/logging.rs index f79d4c72e..3e779cb44 100644 --- a/native/src/base/logging.rs +++ b/native/src/base/logging.rs @@ -5,7 +5,7 @@ use std::panic::Location; use std::process::exit; use crate::ffi::LogLevel; -use crate::{Utf8CStr, Utf8CStrArr}; +use crate::{Utf8CStr, Utf8CStrBufArr}; // Error handling and logging throughout the Rust codebase in Magisk: // @@ -98,7 +98,7 @@ pub fn log_from_cxx(level: LogLevel, msg: &[u8]) { pub fn log_with_formatter fmt::Result>(level: LogLevel, f: F) { log_with_writer(level, |write| { - let mut buf = Utf8CStrArr::default(); + let mut buf = Utf8CStrBufArr::default(); f(&mut buf).ok(); write(level, &buf); }); diff --git a/native/src/base/xwrap.rs b/native/src/base/xwrap.rs index 3fe949211..5144f9d0c 100644 --- a/native/src/base/xwrap.rs +++ b/native/src/base/xwrap.rs @@ -10,7 +10,7 @@ use libc::{ }; use crate::cxx_extern::readlinkat_for_cxx; -use crate::{cstr, errno, raw_cstr, CxxResultExt, FsPath, Utf8CStr, Utf8CStrSlice}; +use crate::{cstr, errno, raw_cstr, CxxResultExt, FsPath, Utf8CStr, Utf8CStrBufRef}; fn ptr_to_str<'a, T>(ptr: *const T) -> &'a str { if ptr.is_null() { @@ -65,7 +65,7 @@ mod c_export { unsafe extern "C" fn xrealpath(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { match Utf8CStr::from_ptr(path) { Ok(p) => { - let mut buf = Utf8CStrSlice::from_ptr(buf, bufsz); + let mut buf = Utf8CStrBufRef::from_ptr(buf, bufsz); FsPath::from(p) .realpath(&mut buf) .log_cxx_with_msg(|w| w.write_fmt(format_args!("realpath {} failed", p))) @@ -79,7 +79,7 @@ unsafe extern "C" fn xrealpath(path: *const c_char, buf: *mut u8, bufsz: usize) unsafe extern "C" fn xreadlink(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { match Utf8CStr::from_ptr(path) { Ok(p) => { - let mut buf = Utf8CStrSlice::from_ptr(buf, bufsz); + let mut buf = Utf8CStrBufRef::from_ptr(buf, bufsz); FsPath::from(p) .read_link(&mut buf) .log_cxx_with_msg(|w| w.write_fmt(format_args!("readlink {} failed", p))) diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index 2333aefac..2e612797a 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -3,7 +3,7 @@ use std::fs::File; use std::io; use std::sync::{Mutex, OnceLock}; -use base::{cstr, Directory, ResultExt, Utf8CStr, Utf8CStrBuf, Utf8CStrSlice, WalkResult}; +use base::{cstr, Directory, ResultExt, Utf8CStr, Utf8CStrBuf, Utf8CStrBufRef, WalkResult}; use crate::logging::{magisk_logging, zygisk_logging}; @@ -57,11 +57,11 @@ pub fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize { Ok(Skip) })?; if !buf.is_empty() { - buf.append("/base.apk"); + buf.push_str("/base.apk"); } Ok(buf.len()) } - inner(pkg, &mut Utf8CStrSlice::from(data)) + inner(pkg, &mut Utf8CStrBufRef::from(data)) .log() .unwrap_or(0) } diff --git a/native/src/core/logging.rs b/native/src/core/logging.rs index c09cfffe2..a490f8aa7 100644 --- a/native/src/core/logging.rs +++ b/native/src/core/logging.rs @@ -245,7 +245,7 @@ extern "C" fn logfile_writer(arg: *mut c_void) -> *mut c_void { let mut meta = LogMeta::zeroed(); let mut msg_buf = [0u8; MAX_MSG_LEN]; - let mut aux = Utf8CStrArr::<64>::new(); + let mut aux = Utf8CStrBufArr::<64>::new(); loop { // Read request diff --git a/native/src/core/resetprop/persist.rs b/native/src/core/resetprop/persist.rs index 59c7f4dc9..4dd8e3b02 100644 --- a/native/src/core/resetprop/persist.rs +++ b/native/src/core/resetprop/persist.rs @@ -13,7 +13,7 @@ use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer}; use base::libc::{O_CLOEXEC, O_RDONLY}; use base::{ clone_attr, cstr, debug, libc::mkstemp, Directory, FsPath, FsPathBuf, LibcReturn, LoggedError, - LoggedResult, MappedFile, Utf8CStr, Utf8CStrArr, WalkResult, + LoggedResult, MappedFile, Utf8CStr, Utf8CStrBufArr, WalkResult, }; use crate::ffi::{prop_cb_exec, PropCb}; @@ -81,7 +81,7 @@ fn check_proto() -> bool { } fn file_get_prop(name: &Utf8CStr) -> LoggedResult { - let mut buf = Utf8CStrArr::default(); + let mut buf = Utf8CStrBufArr::default(); let path = FsPathBuf::new(&mut buf) .join(PERSIST_PROP_DIR!()) .join(name); @@ -93,12 +93,12 @@ fn file_get_prop(name: &Utf8CStr) -> LoggedResult { } fn file_set_prop(name: &Utf8CStr, value: Option<&Utf8CStr>) -> LoggedResult<()> { - let mut buf = Utf8CStrArr::default(); + let mut buf = Utf8CStrBufArr::default(); let path = FsPathBuf::new(&mut buf) .join(PERSIST_PROP_DIR!()) .join(name); if let Some(value) = value { - let mut buf = Utf8CStrArr::default(); + let mut buf = Utf8CStrBufArr::default(); let mut tmp = FsPathBuf::new(&mut buf) .join(PERSIST_PROP_DIR!()) .join("prop.XXXXXX"); @@ -130,7 +130,7 @@ fn proto_read_props() -> LoggedResult { } fn proto_write_props(props: &PersistentProperties) -> LoggedResult<()> { - let mut buf = Utf8CStrArr::default(); + let mut buf = Utf8CStrBufArr::default(); let mut tmp = FsPathBuf::new(&mut buf).join(concat!(PERSIST_PROP!(), ".XXXXXX")); { let f = unsafe {