diff --git a/src/config.rs b/src/config.rs index f4be262b3..459d0f949 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,3 @@ -use std::ffi::CString; - use strum::{EnumProperty, IntoEnumIterator}; use strum_macros::{AsRefStr, Display, EnumIter, EnumProperty, EnumString}; @@ -9,7 +7,6 @@ use crate::dc_job::*; use crate::dc_tools::*; use crate::error::Error; use crate::stock::StockMessage; -use crate::x::*; /// The available configuration keys. #[derive( @@ -72,15 +69,7 @@ impl Context { let value = match key { Config::Selfavatar => { let rel_path = self.sql.get_config(self, key); - rel_path.map(|p| { - let v = unsafe { - let n = CString::yolo(p); - dc_get_abs_path(self, n.as_ptr()) - }; - let r = to_string(v); - unsafe { free(v as *mut _) }; - r - }) + rel_path.map(|p| dc_get_abs_path_safe(self, &p).to_str().unwrap().to_string()) } Config::SysVersion => Some(std::str::from_utf8(DC_VERSION_STR).unwrap().into()), Config::SysMsgsizeMaxRecommended => Some(format!("{}", 24 * 1024 * 1024 / 4 * 3)), diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 814ddd1ab..32f56d807 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -1036,6 +1036,26 @@ pub unsafe fn dc_get_filemeta( 0 } +/// Expand paths relative to $BLOBDIR into absolute paths. +/// +/// If `path` starts with "$BLOBDIR", replaces it with the blobdir path. +/// Otherwise, returns path as is. +pub fn dc_get_abs_path_safe>( + context: &Context, + path: P, +) -> std::path::PathBuf { + let p: &std::path::Path = path.as_ref(); + if let Ok(p) = p.strip_prefix("$BLOBDIR") { + assert!( + context.has_blobdir(), + "Expected context to have blobdir to substitute $BLOBDIR", + ); + std::path::PathBuf::from(as_str(context.get_blobdir())).join(p) + } else { + p.into() + } +} + #[allow(non_snake_case)] pub unsafe fn dc_get_abs_path( context: &Context, @@ -1066,137 +1086,79 @@ pub unsafe fn dc_get_abs_path( pathNfilename_abs } -#[allow(non_snake_case)] -pub unsafe fn dc_file_exist(context: &Context, pathNfilename: *const libc::c_char) -> libc::c_int { - let pathNfilename_abs = dc_get_abs_path(context, pathNfilename); - if pathNfilename_abs.is_null() { - return 0; - } - - let exist = { - let p = std::path::Path::new(as_str(pathNfilename_abs)); - p.exists() - }; - - free(pathNfilename_abs as *mut libc::c_void); - exist as libc::c_int +pub fn dc_file_exist(context: &Context, path: *const libc::c_char) -> libc::c_int { + dc_get_abs_path_safe(context, as_path(path)).exists() as libc::c_int } -#[allow(non_snake_case)] -pub unsafe fn dc_get_filebytes(context: &Context, pathNfilename: *const libc::c_char) -> uint64_t { - let pathNfilename_abs = dc_get_abs_path(context, pathNfilename); - if pathNfilename_abs.is_null() { - return 0; +pub fn dc_get_filebytes(context: &Context, path: *const libc::c_char) -> uint64_t { + let path_abs = dc_get_abs_path_safe(context, as_path(path)); + match fs::metadata(&path_abs) { + Ok(meta) => meta.len() as uint64_t, + Err(_err) => 0, } - - let p = std::ffi::CStr::from_ptr(pathNfilename_abs) - .to_str() - .unwrap(); - let filebytes = match fs::metadata(p) { - Ok(meta) => meta.len(), - Err(_err) => { - return 0; - } - }; - - free(pathNfilename_abs as *mut libc::c_void); - filebytes as uint64_t } -#[allow(non_snake_case)] -pub unsafe fn dc_delete_file(context: &Context, pathNfilename: *const libc::c_char) -> libc::c_int { - let mut success: libc::c_int = 0i32; - let pathNfilename_abs = dc_get_abs_path(context, pathNfilename); - if pathNfilename_abs.is_null() { - return 0; - } - let p = std::path::Path::new( - std::ffi::CStr::from_ptr(pathNfilename_abs) - .to_str() - .unwrap(), - ); - - let res = if p.is_file() { - fs::remove_file(p) +pub fn dc_delete_file(context: &Context, path: *const libc::c_char) -> libc::c_int { + let path = as_path(path); + let path_abs = dc_get_abs_path_safe(context, path); + let res = if path_abs.is_file() { + fs::remove_file(path_abs) } else { - fs::remove_dir_all(p) + fs::remove_dir_all(path_abs) }; match res { - Ok(_) => { - success = 1; - } + Ok(_) => 1, Err(_err) => { - warn!(context, 0, "Cannot delete \"{}\".", as_str(pathNfilename),); + warn!(context, 0, "Cannot delete \"{}\".", path.display()); + 0 } } - - free(pathNfilename_abs as *mut libc::c_void); - success } -#[allow(non_snake_case)] -pub unsafe fn dc_copy_file( +pub fn dc_copy_file( context: &Context, src: *const libc::c_char, dest: *const libc::c_char, ) -> libc::c_int { - let mut success = 0; - - let src_abs = dc_get_abs_path(context, src); - let dest_abs = dc_get_abs_path(context, dest); - - if src_abs.is_null() || dest_abs.is_null() { - return 0; - } - - let src_p = std::ffi::CStr::from_ptr(src_abs).to_str().unwrap(); - let dest_p = std::ffi::CStr::from_ptr(dest_abs).to_str().unwrap(); - - match fs::copy(src_p, dest_p) { - Ok(_) => { - success = 1; - } + let src = as_path(src); + let dest = as_path(dest); + let src_abs = dc_get_abs_path_safe(context, src); + let dest_abs = dc_get_abs_path_safe(context, dest); + match fs::copy(&src_abs, &dest_abs) { + Ok(_) => 1, Err(_) => { - error!(context, 0, "Cannot copy \"{}\" to \"{}\".", src_p, dest_p,); + error!( + context, + 0, + "Cannot copy \"{}\" to \"{}\".", + src.display(), + dest.display(), + ); + 0 } } - - free(src_abs as *mut libc::c_void); - free(dest_abs as *mut libc::c_void); - success } -#[allow(non_snake_case)] -pub unsafe fn dc_create_folder( - context: &Context, - pathNfilename: *const libc::c_char, -) -> libc::c_int { - let mut success = 0; - let pathNfilename_abs = dc_get_abs_path(context, pathNfilename); - { - let p = std::path::Path::new(as_str(pathNfilename_abs)); - if !p.exists() { - match fs::create_dir_all(p) { - Ok(_) => { - success = 1; - } - Err(_err) => { - warn!( - context, - 0, - "Cannot create directory \"{}\".", - as_str(pathNfilename), - ); - } +pub fn dc_create_folder(context: &Context, path: *const libc::c_char) -> libc::c_int { + let path = as_path(path); + let path_abs = dc_get_abs_path_safe(context, path); + if !path_abs.exists() { + match fs::create_dir_all(path_abs) { + Ok(_) => 1, + Err(_err) => { + warn!( + context, + 0, + "Cannot create directory \"{}\".", + path.display(), + ); + 0 } - } else { - success = 1; } + } else { + 1 } - - free(pathNfilename_abs as *mut libc::c_void); - success } #[allow(non_snake_case)] @@ -1211,33 +1173,24 @@ pub unsafe fn dc_write_file( dc_write_file_safe(context, as_str(pathNfilename), bytes) as libc::c_int } -#[allow(non_snake_case)] -pub fn dc_write_file_safe(context: &Context, pathNfilename: impl AsRef, buf: &[u8]) -> bool { - let pathNfilename_abs = unsafe { - let n = CString::yolo(pathNfilename.as_ref()); - dc_get_abs_path(context, n.as_ptr()) - }; - if pathNfilename_abs.is_null() { - return false; - } - - let p = as_str(pathNfilename_abs); - - let success = if let Err(_err) = fs::write(p, buf) { +pub fn dc_write_file_safe>( + context: &Context, + path: P, + buf: &[u8], +) -> bool { + let path_abs = dc_get_abs_path_safe(context, &path); + if let Err(_err) = fs::write(&path_abs, buf) { warn!( context, 0, "Cannot write {} bytes to \"{}\".", buf.len(), - pathNfilename.as_ref(), + path.as_ref().display(), ); false } else { true - }; - - unsafe { free(pathNfilename_abs as *mut libc::c_void) }; - success + } } #[allow(non_snake_case)] @@ -1260,34 +1213,20 @@ pub unsafe fn dc_read_file( } } -#[allow(non_snake_case)] -pub fn dc_read_file_safe(context: &Context, pathNfilename: impl AsRef) -> Option> { - let pathNfilename_abs = unsafe { - let n = CString::yolo(pathNfilename.as_ref()); - dc_get_abs_path(context, n.as_ptr()) - }; - - if pathNfilename_abs.is_null() { - return None; - } - - let p = as_str(pathNfilename_abs); - let res = match fs::read(p) { +pub fn dc_read_file_safe>(context: &Context, path: P) -> Option> { + let path_abs = dc_get_abs_path_safe(context, &path); + match fs::read(&path_abs) { Ok(bytes) => Some(bytes), Err(_err) => { warn!( context, 0, "Cannot read \"{}\" or file is empty.", - pathNfilename.as_ref(), + path.as_ref().display() ); None } - }; - - unsafe { free(pathNfilename_abs as *mut libc::c_void) }; - - res + } } #[allow(non_snake_case)] diff --git a/src/sql.rs b/src/sql.rs index 2264e3c0e..079130648 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -1047,10 +1047,8 @@ pub fn housekeeping(context: &Context) { unreferenced_count, entry.file_name() ); - unsafe { - let path = entry.path().to_c_string().unwrap(); - dc_delete_file(context, path.as_ptr()); - } + let path = entry.path().to_c_string().unwrap(); + dc_delete_file(context, path.as_ptr()); } } Err(err) => {