@@ -13,3 +13,57 @@ pub(crate) mod metrics;
1313pub ( crate ) mod proto_adapter;
1414pub ( crate ) mod systemd;
1515pub ( crate ) mod tls;
16+
17+ use std:: fs:: { self , OpenOptions } ;
18+ use std:: io:: { self , Write } ;
19+ use std:: os:: unix:: fs:: { OpenOptionsExt , PermissionsExt } ;
20+ use std:: path:: Path ;
21+
22+ pub ( crate ) fn write_new ( path : & Path , contents : & [ u8 ] , mode : u32 ) -> io:: Result < ( ) > {
23+ let mut file = OpenOptions :: new ( ) . create_new ( true ) . write ( true ) . mode ( mode) . open ( path) ?;
24+ file. write_all ( contents) ?;
25+ fs:: set_permissions ( path, fs:: Permissions :: from_mode ( mode) ) ?;
26+ file. sync_all ( ) ?;
27+ Ok ( ( ) )
28+ }
29+
30+ #[ cfg( test) ]
31+ mod tests {
32+ use super :: * ;
33+ use std:: path:: PathBuf ;
34+
35+ #[ test]
36+ fn write_new_sets_requested_mode_and_contents ( ) {
37+ let dir = test_dir ( "mode_and_contents" ) ;
38+ let path = dir. join ( "secret" ) ;
39+
40+ write_new ( & path, b"secret-bytes" , 0o400 ) . unwrap ( ) ;
41+
42+ assert_eq ! ( fs:: read( & path) . unwrap( ) , b"secret-bytes" ) ;
43+ assert_eq ! ( fs:: metadata( & path) . unwrap( ) . permissions( ) . mode( ) & 0o777 , 0o400 ) ;
44+
45+ fs:: remove_dir_all ( dir) . unwrap ( ) ;
46+ }
47+
48+ #[ test]
49+ fn write_new_does_not_replace_existing_file ( ) {
50+ let dir = test_dir ( "existing_file" ) ;
51+ let path = dir. join ( "secret" ) ;
52+ fs:: write ( & path, b"original" ) . unwrap ( ) ;
53+
54+ let err = write_new ( & path, b"replacement" , 0o400 ) . unwrap_err ( ) ;
55+
56+ assert_eq ! ( err. kind( ) , io:: ErrorKind :: AlreadyExists ) ;
57+ assert_eq ! ( fs:: read( & path) . unwrap( ) , b"original" ) ;
58+
59+ fs:: remove_dir_all ( dir) . unwrap ( ) ;
60+ }
61+
62+ fn test_dir ( name : & str ) -> PathBuf {
63+ let dir = std:: env:: temp_dir ( )
64+ . join ( format ! ( "ldk-server-secure-file-test-{name}-{}" , std:: process:: id( ) ) ) ;
65+ let _ = fs:: remove_dir_all ( & dir) ;
66+ fs:: create_dir ( & dir) . unwrap ( ) ;
67+ dir
68+ }
69+ }
0 commit comments