Atomic create new files with permissions to owner in ethstore (#8896)

* Atomic create new files with permissions to owner in ethstore

* Allow replacing existing files

We have two behaviors for `insert_with_filename` depending on whether `dedup` is true.  Add
`replace_file_with_permissions_to_owner` which use `OpenOptions::create(true)` instead of `create_new`.
This commit is contained in:
Wei Tang 2018-06-14 19:54:12 +08:00 committed by Marek Kotewicz
parent 9546e0c8c2
commit fc86b1799a

View File

@ -33,22 +33,43 @@ const IGNORED_FILES: &'static [&'static str] = &[
"vault.json",
];
#[cfg(not(windows))]
fn restrict_permissions_to_owner(file_path: &Path) -> Result<(), i32> {
use std::ffi;
#[cfg(unix)]
fn create_new_file_with_permissions_to_owner(file_path: &Path) -> io::Result<fs::File> {
use libc;
use std::os::unix::fs::OpenOptionsExt;
let cstr = ffi::CString::new(&*file_path.to_string_lossy())
.map_err(|_| -1)?;
match unsafe { libc::chmod(cstr.as_ptr(), libc::S_IWUSR | libc::S_IRUSR) } {
0 => Ok(()),
x => Err(x),
}
fs::OpenOptions::new()
.write(true)
.create_new(true)
.mode(libc::S_IWUSR | libc::S_IRUSR)
.open(file_path)
}
#[cfg(windows)]
fn restrict_permissions_to_owner(_file_path: &Path) -> Result<(), i32> {
Ok(())
#[cfg(not(unix))]
fn create_new_file_with_permissions_to_owner(file_path: &Path) -> io::Result<fs::File> {
fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(file_path)
}
#[cfg(unix)]
fn replace_file_with_permissions_to_owner(file_path: &Path) -> io::Result<fs::File> {
use libc;
use std::os::unix::fs::PermissionsExt;
let file = fs::File::create(file_path)?;
let mut permissions = file.metadata()?.permissions();
permissions.set_mode(libc::S_IWUSR | libc::S_IRUSR);
file.set_permissions(permissions)?;
Ok(file)
}
#[cfg(not(unix))]
fn replace_file_with_permissions_to_owner(file_path: &Path) -> io::Result<fs::File> {
fs::File::create(file_path)
}
/// Root keys directory implementation
@ -173,17 +194,16 @@ impl<T> DiskDirectory<T> where T: KeyFileManager {
{
// save the file
let mut file = fs::File::create(&keyfile_path)?;
let mut file = if dedup {
create_new_file_with_permissions_to_owner(&keyfile_path)?
} else {
replace_file_with_permissions_to_owner(&keyfile_path)?
};
// write key content
self.key_manager.write(original_account, &mut file).map_err(|e| Error::Custom(format!("{:?}", e)))?;
file.flush()?;
if let Err(_) = restrict_permissions_to_owner(keyfile_path.as_path()) {
return Err(Error::Io(io::Error::last_os_error()));
}
file.sync_all()?;
}