X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fp5-File-KDBX;a=blobdiff_plain;f=lib%2FFile%2FKDBX%2FKey%2FFile.pm;h=335b31e367fdf91bff45a4a13a69701577fd9826;hp=5c7cb12645d2f3bdd7f763924eb004f8f5d4bef7;hb=63d73bf382edfb0089b36a45193fc2835cb58b6d;hpb=1b913e5c8826cae2355b0076ec5701aa3ce63c63 diff --git a/lib/File/KDBX/Key/File.pm b/lib/File/KDBX/Key/File.pm index 5c7cb12..335b31e 100644 --- a/lib/File/KDBX/Key/File.pm +++ b/lib/File/KDBX/Key/File.pm @@ -9,16 +9,46 @@ use Crypt::Misc 0.029 qw(decode_b64 encode_b64); use Crypt::PRNG qw(random_bytes); use File::KDBX::Constants qw(:key_file); use File::KDBX::Error; -use File::KDBX::Util qw(:erase trim); +use File::KDBX::Util qw(:class :erase trim); use Ref::Util qw(is_ref is_scalarref); use Scalar::Util qw(openhandle); use XML::LibXML::Reader; use namespace::clean; -use parent 'File::KDBX::Key'; +extends 'File::KDBX::Key'; our $VERSION = '999.999'; # VERSION +=attr type + + $type = $key->type; + +Get the type of key file. Can be one of from L: + +=for :list +* C +* C +* C +* C + +=attr version + + $version = $key->version; + +Get the file version. Only applies to XML key files. + +=attr filepath + + $filepath = $key->filepath; + +Get the filepath to the key file, if known. + +=cut + +has 'type', is => 'ro'; +has 'version', is => 'ro'; +has 'filepath', is => 'ro'; + =method load $key = $key->load($filepath); @@ -97,42 +127,6 @@ sub reload { return $self; } -=attr type - - $type = $key->type; - -Get the type of key file. Can be one of: - -=for :list -* C -* C -* C -* C - -=cut - -sub type { $_[0]->{type} } - -=attr version - - $version = $key->version; - -Get the file version. Only applies to XML key files. - -=cut - -sub version { $_[0]->{version} } - -=attr filepath - - $filepath = $key->filepath; - -Get the filepath to the key file, if known. - -=cut - -sub filepath { $_[0]->{filepath} } - =method save $key->save; @@ -163,9 +157,18 @@ sub save { my $filepath = $args{filepath} // $self->filepath; my $fh = $args{fh}; + my $filepath_temp; if (!openhandle($fh)) { $filepath or throw 'Must specify where to safe the key file to'; - open($fh, '>:raw', $filepath) or throw "Failed to open key file for writing: $!"; + + require File::Temp; + ($fh, $filepath_temp) = eval { File::Temp::tempfile("${filepath}-XXXXXX", CLEANUP => 1) }; + if (!$fh or my $err = $@) { + $err //= 'Unknown error'; + throw sprintf('Open file failed (%s): %s', $filepath_temp, $err), + error => $err, + filepath => $filepath_temp; + } } if ($type == KEY_FILE_TYPE_XML) { @@ -182,6 +185,20 @@ sub save { else { throw "Cannot save $type key file (invalid type)", type => $type; } + + close($fh); + + if ($filepath_temp) { + my ($file_mode, $file_uid, $file_gid) = (stat($filepath))[2, 4, 5]; + + my $mode = $args{mode} // $file_mode // do { my $m = umask; defined $m ? oct(666) &~ $m : undef }; + my $uid = $args{uid} // $file_uid // -1; + my $gid = $args{gid} // $file_gid // -1; + chmod($mode, $filepath_temp) if defined $mode; + chown($uid, $gid, $filepath_temp); + rename($filepath_temp, $filepath) + or throw "Failed to write file ($filepath): $!", filepath => $filepath; + } } ##############################################################################