@@ -11,8 +11,8 @@ use crate::path::Arg;
1111use crate :: sync;
1212
1313use super :: errors:: {
14- ChmodError , CloseError , FileStatusError , MetadataError , MkdirError , OpenError , PathError ,
15- ReadError , RmdirError , SeekError , SetMetadataError , UnlinkError , WriteError ,
14+ ChmodError , ChownError , CloseError , FileStatusError , MetadataError , MkdirError , OpenError ,
15+ PathError , ReadError , RmdirError , SeekError , SetMetadataError , UnlinkError , WriteError ,
1616} ;
1717use super :: { FileStatus , Mode , SeekWhence } ;
1818use crate :: utilities:: anymap:: AnyMap ;
@@ -74,6 +74,21 @@ impl<Platform: sync::RawSyncPrimitivesProvider> FileSystem<Platform> {
7474 unreachable ! ( )
7575 }
7676 }
77+
78+ /// Execute `f` as a specific user (for testing purposes).
79+ #[ cfg( test) ]
80+ pub fn with_user < F > ( & mut self , user : u16 , group : u16 , f : F )
81+ where
82+ F : FnOnce ( & mut Self ) ,
83+ {
84+ let test_user = UserInfo { user, group } ;
85+ let original_user = core:: mem:: replace ( & mut self . current_user , test_user) ;
86+ f ( self ) ;
87+ let test_user_again = core:: mem:: replace ( & mut self . current_user , original_user) ;
88+ if test_user_again. user != test_user. user || test_user_again. group != test_user. group {
89+ unreachable ! ( )
90+ }
91+ }
7792}
7893
7994impl < Platform : sync:: RawSyncPrimitivesProvider > super :: private:: Sealed for FileSystem < Platform > { }
@@ -313,6 +328,48 @@ impl<Platform: sync::RawSyncPrimitivesProvider> super::FileSystem for FileSystem
313328 }
314329 }
315330
331+ fn chown (
332+ & self ,
333+ path : impl crate :: path:: Arg ,
334+ user : Option < u16 > ,
335+ group : Option < u16 > ,
336+ ) -> Result < ( ) , ChownError > {
337+ let path = self . absolute_path ( path) ?;
338+ let mut root = self . root . write ( ) ;
339+ let ( _, entry) = root. parent_and_entry ( & path, self . current_user ) ?;
340+ let Some ( entry) = entry else {
341+ return Err ( PathError :: NoSuchFileOrDirectory ) ?;
342+ } ;
343+ match entry {
344+ Entry :: File ( file) => {
345+ let perms = & mut file. write ( ) . perms ;
346+ if !( self . current_user . user == 0 || self . current_user . user == perms. userinfo . user ) {
347+ return Err ( ChownError :: NotTheOwner ) ;
348+ }
349+ if let Some ( new_user) = user {
350+ perms. userinfo . user = new_user;
351+ }
352+ if let Some ( new_group) = group {
353+ perms. userinfo . group = new_group;
354+ }
355+ Ok ( ( ) )
356+ }
357+ Entry :: Dir ( dir) => {
358+ let perms = & mut dir. write ( ) . perms ;
359+ if !( self . current_user . user == 0 || self . current_user . user == perms. userinfo . user ) {
360+ return Err ( ChownError :: NotTheOwner ) ;
361+ }
362+ if let Some ( new_user) = user {
363+ perms. userinfo . user = new_user;
364+ }
365+ if let Some ( new_group) = group {
366+ perms. userinfo . group = new_group;
367+ }
368+ Ok ( ( ) )
369+ }
370+ }
371+ }
372+
316373 fn unlink ( & self , path : impl crate :: path:: Arg ) -> Result < ( ) , UnlinkError > {
317374 let path = self . absolute_path ( path) ?;
318375 let mut root = self . root . write ( ) ;
0 commit comments