@ -6,7 +6,84 @@ use std::{
} ,
} ,
error ,
error ,
fmt ,
fmt ,
io ,
} ;
} ;
use tokio ::{
prelude ::* ,
fs ::{
OpenOptions ,
File ,
} ,
io ::{
BufReader ,
} ,
} ;
use config ::op ::KeyFormat ;
/// Find the format (Binary, Text, PEM) of this key file.
///
/// # Note
/// This isn't an infallible test as it only parses parts of headers, if it detects a type it doesn't guarantee that the file *actually* is that type. It is just a hint or best-guess.
#[ instrument(err, skip(path), fields(path = ?path.as_ref())) ]
pub async fn find_key_format ( path : impl AsRef < Path > , can_pem : bool ) -> eyre ::Result < KeyFormat >
{
async fn check_bin ( file : & mut File ) -> Result < bool , Error >
{
let mut buffer = [ 0 u8 ; 4 ] ;
file . read_exact ( & mut buffer [ .. ] ) . await ? ;
Ok ( & buffer [ .. ] = = format ::RAE_HEADER_BIT )
}
async fn check_text ( file : & mut File ) -> Result < bool , Error >
{
let mut buffer = [ 0 u8 ; 4 ] ;
file . read_exact ( & mut buffer [ .. ] ) . await ? ;
if & buffer [ .. ] ! = b" --- " {
return Ok ( false ) ;
}
file . read_exact ( & mut buffer [ .. ] ) . await ? ;
Ok ( & buffer [ .. ] = = format ::RAE_HEADER_BIT )
}
async fn check_pem ( file : & mut File ) -> Result < bool , Error >
{
todo! ( "I don't remember the PEM format right now" )
}
let mut file = {
let path = path . as_ref ( ) ;
OpenOptions ::new ( )
. read ( true )
. open ( path ) . await
. wrap_err ( eyre ::eyre ! ( "Failed to open file to check" ) )
. with_section ( | | format! ( "{:?}" , path ) . header ( "Path was" ) ) ?
} ;
macro_rules! reset {
( ) = > {
file . seek ( std ::io ::SeekFrom ::Start ( 0 ) ) . await ?
}
}
if can_pem {
if check_pem ( & mut file ) . await
. with_note ( | | "With check for PEM" ) ? {
return Ok ( KeyFormat ::PEM ) ;
} else {
reset ! ( ) ;
}
}
if check_bin ( & mut file ) . await
. with_note ( | | "With check for binary" ) ? {
return Ok ( KeyFormat ::Bin ) ;
} else {
reset ! ( ) ;
}
if check_text ( & mut file ) . await
. with_note ( | | "With check for text" ) ? {
return Ok ( KeyFormat ::Text ) ;
}
return Err ( Error ::UnknownFormat ) ? ;
}
pub async fn find_file_mode < P : AsRef < Path > > ( path : P ) -> Result < config ::op ::Mode , Error >
pub async fn find_file_mode < P : AsRef < Path > > ( path : P ) -> Result < config ::op ::Mode , Error >
{
{
@ -26,7 +103,9 @@ pub async fn find_key_mode<P: AsRef<Path>>(path: P) -> Result<config::KeyKind, E
#[ non_exhaustive ]
#[ non_exhaustive ]
pub enum Error
pub enum Error
{
{
Unknown
UnknownFormat ,
IO ( io ::Error ) ,
Unknown ,
}
}
impl error ::Error for Error { }
impl error ::Error for Error { }
@ -39,3 +118,11 @@ impl fmt::Display for Error
}
}
}
}
}
}
impl From < io ::Error > for Error
{
#[ inline ] fn from ( from : io ::Error ) -> Self
{
Self ::IO ( from )
}
}