dropfile
This commit is contained in:
parent
350ccae12a
commit
2a6f6a0413
@ -3,12 +3,9 @@ name = "acmec"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.136", features = ["derive"] }
|
||||
reqwest = { version = "*", features = ["blocking", "json"] }
|
||||
openssl = "0.10.38"
|
||||
serde_json = "1.0.79"
|
||||
|
||||
[features]
|
||||
dropfile = { git = "https://github.com/bridgeloop/dropfile.git" }
|
@ -1,55 +0,0 @@
|
||||
use std::{fs::File, io::{Seek, Write}};
|
||||
|
||||
pub struct CleanFile {
|
||||
path: String,
|
||||
file: Option<File>,
|
||||
created: bool,
|
||||
written_to: bool,
|
||||
}
|
||||
impl CleanFile {
|
||||
pub fn open(path: String, create: bool) -> Result<Self, &'static str> {
|
||||
let mut file_options = File::options();
|
||||
file_options.read(true).write(true).create_new(create);
|
||||
|
||||
let file = file_options.open(&(path)).map_err(|err| match err.kind() {
|
||||
std::io::ErrorKind::AlreadyExists => "file already exists",
|
||||
_ => "failed to open file"
|
||||
})?;
|
||||
|
||||
return Ok(Self { path, file: Some(file), created: create, written_to: false, });
|
||||
}
|
||||
|
||||
fn delete_file(&mut self) -> Result<(), &'static str> {
|
||||
return if let Some(_) = self.file.take() {
|
||||
std::fs::remove_file(&(self.path)).map_err(|_| "failed to delete file")
|
||||
} else { Ok(()) };
|
||||
}
|
||||
pub fn delete(mut self) -> Result<(), &'static str> {
|
||||
return self.delete_file();
|
||||
}
|
||||
|
||||
pub fn write<T: AsRef<[u8]>>(&mut self, bytes: T) -> Result<(), &'static str> {
|
||||
let file: &mut File = self.file.as_mut().ok_or("file deleted")?;
|
||||
file.set_len(0).map_err(|_| "failed to truncate file")?;
|
||||
file.seek(std::io::SeekFrom::Start(0)).map_err(|_| "failed to seek file")?;
|
||||
file.write_all(bytes.as_ref()).map_err(|_| "failed to write to file")?;
|
||||
|
||||
self.written_to = true;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn file(&self) -> Result<&File, &'static str> {
|
||||
return self.file.as_ref().ok_or("file deleted");
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &str {
|
||||
return &(self.path);
|
||||
}
|
||||
}
|
||||
impl Drop for CleanFile {
|
||||
fn drop(&mut self) {
|
||||
if self.created && !self.written_to {
|
||||
self.delete_file().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use crate::{clean_file::CleanFile, stringify_ser};
|
||||
use std::{ops::{Deref, DerefMut}, path::Path};
|
||||
use crate::stringify_ser;
|
||||
use dropfile::DropFile;
|
||||
|
||||
mod acmec_config;
|
||||
use acmec_config::AcmecConfig;
|
||||
@ -22,20 +23,20 @@ pub struct OrderDetails {
|
||||
}
|
||||
|
||||
pub struct ConfigFile {
|
||||
clean_file: Option<CleanFile>,
|
||||
file: Option<DropFile>,
|
||||
config: AcmecConfig,
|
||||
}
|
||||
impl ConfigFile {
|
||||
pub fn open(path: String, create: bool) -> Result<Self, &'static str> {
|
||||
let clean_file = CleanFile::open(path, create)?;
|
||||
let config: AcmecConfig = serde_json::from_reader(clean_file.file().unwrap()).unwrap_or_default();
|
||||
return Ok(Self { clean_file: Some(clean_file), config, });
|
||||
let mut file = DropFile::open(path, create)?;
|
||||
let config: AcmecConfig = serde_json::from_reader(&mut(file)).unwrap_or_default();
|
||||
return Ok(Self { file: Some(file), config, });
|
||||
}
|
||||
pub fn delete(mut self) -> Result<(), &'static str> {
|
||||
return self.clean_file.take().unwrap().delete();
|
||||
return self.file.take().unwrap().delete();
|
||||
}
|
||||
pub fn path(&self) -> &str {
|
||||
return self.clean_file.as_ref().unwrap().path();
|
||||
pub fn path(&self) -> &Path {
|
||||
return self.file.as_ref().unwrap().path();
|
||||
}
|
||||
}
|
||||
impl Deref for ConfigFile {
|
||||
@ -51,12 +52,12 @@ impl DerefMut for ConfigFile {
|
||||
}
|
||||
impl Drop for ConfigFile {
|
||||
fn drop(&mut self) {
|
||||
let Some(mut clean_file) = self.clean_file.take() else {
|
||||
let Some(mut file) = self.file.take() else {
|
||||
return;
|
||||
};
|
||||
if self.changed() {
|
||||
let json_config = stringify_ser(&(self.config)).unwrap();
|
||||
clean_file.write(json_config).unwrap();
|
||||
file.write_trunc(json_config.as_bytes()).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
22
src/main.rs
22
src/main.rs
@ -38,13 +38,11 @@ use openssl::{
|
||||
};
|
||||
use reqwest::{self, header::HeaderValue, blocking::{Client as HttpClient, Response as HttpResponse}};
|
||||
use {serde, serde_json};
|
||||
use dropfile::DropFile;
|
||||
|
||||
mod acme;
|
||||
use acme::*;
|
||||
|
||||
mod clean_file;
|
||||
use clean_file::*;
|
||||
|
||||
mod config_file;
|
||||
use config_file::*;
|
||||
|
||||
@ -303,7 +301,7 @@ fn main() -> Result<(), &'static str> {
|
||||
let config_file = ConfigFile::open(config_path, false)?;
|
||||
let mut context = AcmecContext::with_config_file(&(config_file), pem_passphrase)?;
|
||||
|
||||
println!("REALLY delete \"{}\"? this cannot be undone! [yes / any other line]", config_file.path());
|
||||
println!("REALLY delete \"{}\"? this cannot be undone! [yes / any other line]", config_file.path().display());
|
||||
let mut buf = String::new();
|
||||
std::io::stdin().read_line(&mut(buf)).expect("failed to read line from stdin");
|
||||
if buf != "yes\n" {
|
||||
@ -381,8 +379,8 @@ fn main() -> Result<(), &'static str> {
|
||||
let cert_path = args_iter.next().ok_or("expected path to cert file")?;
|
||||
let pkey_path = args_iter.next().ok_or("expected path to pkey file")?;
|
||||
|
||||
let mut cert_file = CleanFile::open(cert_path, true)?;
|
||||
let mut pkey_file = CleanFile::open(pkey_path, true)?;
|
||||
let mut cert_file = DropFile::open(cert_path, true)?;
|
||||
let mut pkey_file = DropFile::open(pkey_path, true)?;
|
||||
|
||||
for url in &(order.challenges) {
|
||||
acme_post(&mut(context), &(url), "{}")?;
|
||||
@ -449,11 +447,11 @@ fn main() -> Result<(), &'static str> {
|
||||
.text()
|
||||
.map_err(|_| "failed to read response")?;
|
||||
|
||||
if let Err(_) = cert_file.write(&(cert)) {
|
||||
if let Err(_) = cert_file.write_trunc(cert.as_bytes()) {
|
||||
eprintln!("failed to write certificate to file, printing to stdout instead");
|
||||
println!("{}", cert);
|
||||
}
|
||||
if let Err(_) = pkey_file.write(&*(pkey_pem)) {
|
||||
if let Err(_) = pkey_file.write_trunc(pkey_pem) {
|
||||
eprintln!("failed to write private key to file, printing to stdout instead");
|
||||
println!("{}", pkey_pem_view);
|
||||
}
|
||||
@ -488,14 +486,14 @@ fn main() -> Result<(), &'static str> {
|
||||
builder.sign(&(kp), MessageDigest::sha256()).unwrap();
|
||||
let cert_pem = builder.build().to_pem().map_err(|_| "failed to encode certificate as pem")?;
|
||||
|
||||
let mut cert_file = CleanFile::open(cert_path, true)?;
|
||||
let mut priv_file = CleanFile::open(key_path, true)?;
|
||||
let mut cert_file = DropFile::open(cert_path, true)?;
|
||||
let mut priv_file = DropFile::open(key_path, true)?;
|
||||
|
||||
if let Err(_) = cert_file.write(&(cert_pem)) {
|
||||
if let Err(_) = cert_file.write_trunc(&(cert_pem)) {
|
||||
eprintln!("failed to write certificate! printing to stdout instead...");
|
||||
println!("{}", from_utf8(&(cert_pem)).unwrap());
|
||||
}
|
||||
if let Err(_) = priv_file.write(&(priv_pem)) {
|
||||
if let Err(_) = priv_file.write_trunc(&(priv_pem)) {
|
||||
eprintln!("failed to write private key! printing to stdout instead...");
|
||||
println!("{}", from_utf8(&(priv_pem)).unwrap());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user