11use crate :: {
22 chunk:: { self , AcePlatform , Identifier , OwnerType } ,
33 utils:: os:: windows:: {
4- fs:: { open_read_metadata, open_write_dacl} ,
4+ fs:: { FileHandle , open_read_metadata, open_write_dacl} ,
55 security:: { SecurityDescriptor , Sid , SidType } ,
66 } ,
77} ;
88use field_offset:: offset_of;
99use std:: { io, mem, path:: Path , ptr:: null_mut} ;
10- use windows:: Win32 :: Foundation :: HANDLE ;
1110use windows:: Win32 :: Security :: {
1211 ACCESS_ALLOWED_ACE , ACCESS_DENIED_ACE , ACE_FLAGS , ACE_HEADER , ACL as Win32ACL , ACL_REVISION_DS ,
1312 AddAccessAllowedAceEx , AddAccessDeniedAceEx , CONTAINER_INHERIT_ACE , GetAce , INHERIT_ONLY_ACE ,
@@ -21,8 +20,13 @@ use windows::Win32::Storage::FileSystem::{
2120} ;
2221use windows:: Win32 :: System :: SystemServices :: { ACCESS_ALLOWED_ACE_TYPE , ACCESS_DENIED_ACE_TYPE } ;
2322
24- pub fn set_facl < P : AsRef < Path > > ( path : P , ace_list : chunk:: Acl ) -> io:: Result < ( ) > {
25- let acl = ACL :: try_from ( path. as_ref ( ) ) ?;
23+ pub fn set_facl < P : AsRef < Path > > (
24+ path : P ,
25+ ace_list : chunk:: Acl ,
26+ follow_links : bool ,
27+ ) -> io:: Result < ( ) > {
28+ let handle = open_write_dacl ( path. as_ref ( ) , follow_links) ?;
29+ let acl = ACL :: try_from_handle ( handle) ?;
2630 let group_sid = acl. security_descriptor . group_sid ( ) ?;
2731 let owner_sid = acl. security_descriptor . owner_sid ( ) ?;
2832 let acl_entries = ace_list
@@ -33,31 +37,9 @@ pub fn set_facl<P: AsRef<Path>>(path: P, ace_list: chunk::Acl) -> io::Result<()>
3337 acl. set_d_acl ( & acl_entries)
3438}
3539
36- pub fn get_facl < P : AsRef < Path > > ( path : P ) -> io:: Result < chunk:: Acl > {
37- let acl = ACL :: try_from ( path. as_ref ( ) ) ?;
38- let ace_list = acl. get_d_acl ( ) ?;
39- Ok ( chunk:: Acl {
40- platform : AcePlatform :: Windows ,
41- entries : ace_list. into_iter ( ) . map ( Into :: into) . collect ( ) ,
42- } )
43- }
44-
45- pub fn set_facl_nofollow < P : AsRef < Path > > ( path : P , ace_list : chunk:: Acl ) -> io:: Result < ( ) > {
46- let path = path. as_ref ( ) ;
47- let handle = open_write_dacl ( path, false ) ?;
48- let acl = ACL :: try_from_handle ( handle. raw ( ) , path) ?;
49- let group_sid = acl. security_descriptor . group_sid ( ) ?;
50- let owner_sid = acl. security_descriptor . owner_sid ( ) ?;
51- let acl_entries = ace_list
52- . entries
53- . into_iter ( )
54- . map ( |it| it. into_acl_entry_with ( & owner_sid, & group_sid) )
55- . collect :: < Vec < _ > > ( ) ;
56- acl. set_d_acl_by_handle ( handle. raw ( ) , & acl_entries)
57- }
58-
59- pub fn get_facl_nofollow < P : AsRef < Path > > ( path : P ) -> io:: Result < chunk:: Acl > {
60- let acl = ACL :: try_from_nofollow ( path. as_ref ( ) ) ?;
40+ pub fn get_facl < P : AsRef < Path > > ( path : P , follow_links : bool ) -> io:: Result < chunk:: Acl > {
41+ let handle = open_read_metadata ( path. as_ref ( ) , follow_links) ?;
42+ let acl = ACL :: try_from_handle ( handle) ?;
6143 let ace_list = acl. get_d_acl ( ) ?;
6244 Ok ( chunk:: Acl {
6345 platform : AcePlatform :: Windows ,
@@ -74,22 +56,9 @@ pub struct ACL {
7456}
7557
7658impl ACL {
77- pub fn try_from ( path : & Path ) -> io:: Result < Self > {
59+ pub fn try_from_handle ( handle : FileHandle ) -> io:: Result < Self > {
7860 Ok ( Self {
79- security_descriptor : SecurityDescriptor :: try_from ( path) ?,
80- } )
81- }
82-
83- pub fn try_from_nofollow ( path : & Path ) -> io:: Result < Self > {
84- let handle = open_read_metadata ( path, false ) ?;
85- Ok ( Self {
86- security_descriptor : SecurityDescriptor :: try_from_handle ( handle. raw ( ) , path) ?,
87- } )
88- }
89-
90- pub fn try_from_handle ( handle : HANDLE , path : & Path ) -> io:: Result < Self > {
91- Ok ( Self {
92- security_descriptor : SecurityDescriptor :: try_from_handle ( handle, path) ?,
61+ security_descriptor : SecurityDescriptor :: try_from_handle ( handle) ?,
9362 } )
9463 }
9564
@@ -154,11 +123,6 @@ impl ACL {
154123 self . security_descriptor
155124 . apply ( None , None , Some ( buffer. as_ptr ( ) as _ ) )
156125 }
157-
158- pub fn set_d_acl_by_handle ( & self , handle : HANDLE , acl_entries : & [ ACLEntry ] ) -> io:: Result < ( ) > {
159- let buffer = build_acl_buffer ( acl_entries) ?;
160- SecurityDescriptor :: apply_by_handle ( handle, None , None , Some ( buffer. as_ptr ( ) as _ ) )
161- }
162126}
163127
164128fn build_acl_buffer ( acl_entries : & [ ACLEntry ] ) -> io:: Result < Vec < u8 > > {
@@ -167,6 +131,7 @@ fn build_acl_buffer(acl_entries: &[ACLEntry]) -> io::Result<Vec<u8>> {
167131 let mut buffer = Vec :: < u8 > :: with_capacity ( acl_size) ;
168132 let ptr = buffer. as_mut_ptr ( ) ;
169133 unsafe { InitializeAcl ( ptr as _ , acl_size as u32 , ACL_REVISION_DS ) } ?;
134+ unsafe { buffer. set_len ( acl_size) } ;
170135 for ace in acl_entries {
171136 match ace. ace_type {
172137 AceType :: AccessAllow => unsafe {
@@ -382,9 +347,10 @@ mod tests {
382347 | chunk:: Permission :: EXECUTE ,
383348 } ] ,
384349 } ) ,
350+ true ,
385351 )
386352 . unwrap ( ) ;
387- let acl = get_facl ( file. path ) . unwrap ( ) ;
353+ let acl = get_facl ( file. path , true ) . unwrap ( ) ;
388354 assert_eq ! ( acl. entries. len( ) , 1 ) ;
389355
390356 assert_eq ! (
@@ -418,7 +384,7 @@ mod tests {
418384 fn get_acl ( ) {
419385 let file = AutoRemoveFile :: new ( "default.txt" ) ;
420386 file. write ( "default" ) . unwrap ( ) ;
421- let acl = get_facl ( file. path ) . unwrap ( ) ;
387+ let acl = get_facl ( file. path , true ) . unwrap ( ) ;
422388 assert_ne ! ( acl. entries. len( ) , 0 ) ;
423389 }
424390}
0 commit comments