@@ -119,6 +119,14 @@ pub trait CapStdExtDirExt {
119
119
contents : impl AsRef < [ u8 ] > ,
120
120
perms : cap_std:: fs:: Permissions ,
121
121
) -> Result < ( ) > ;
122
+
123
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
124
+ /// Returns `Some(true)` if the target is known to be a mountpoint, or
125
+ /// `Some(false)` if the target is definitively known not to be a mountpoint.
126
+ ///
127
+ /// In some scenarios (such as an older kernel) this currently may not be possible
128
+ /// to determine, and `None` will be returned in those cases.
129
+ fn is_mountpoint ( & self , path : impl AsRef < Path > ) -> Result < Option < bool > > ;
122
130
}
123
131
124
132
#[ cfg( feature = "fs_utf8" ) ]
@@ -300,6 +308,28 @@ fn subdir_of<'d, 'p>(d: &'d Dir, p: &'p Path) -> io::Result<(DirOwnedOrBorrowed<
300
308
Ok ( ( r, name) )
301
309
}
302
310
311
+ fn is_mountpoint_impl_statx ( root : & Dir , path : & Path ) -> Result < Option < bool > > {
312
+ // https://github.com/systemd/systemd/blob/8fbf0a214e2fe474655b17a4b663122943b55db0/src/basic/mountpoint-util.c#L176
313
+ use rustix:: fs:: { AtFlags , StatxFlags } ;
314
+ use std:: os:: fd:: AsFd ;
315
+
316
+ // SAFETY(unwrap): We can infallibly convert an i32 into a u64.
317
+ let mountroot_flag: u64 = libc:: STATX_ATTR_MOUNT_ROOT . try_into ( ) . unwrap ( ) ;
318
+ match rustix:: fs:: statx (
319
+ root. as_fd ( ) ,
320
+ path,
321
+ AtFlags :: NO_AUTOMOUNT | AtFlags :: SYMLINK_NOFOLLOW ,
322
+ StatxFlags :: empty ( ) ,
323
+ ) {
324
+ Ok ( r) => {
325
+ let present = ( r. stx_attributes_mask & mountroot_flag) > 0 ;
326
+ Ok ( present. then_some ( r. stx_attributes & mountroot_flag > 0 ) )
327
+ }
328
+ Err ( e) if e == rustix:: io:: Errno :: NOSYS => Ok ( None ) ,
329
+ Err ( e) => Err ( e. into ( ) ) ,
330
+ }
331
+ }
332
+
303
333
impl CapStdExtDirExt for Dir {
304
334
fn open_optional ( & self , path : impl AsRef < Path > ) -> Result < Option < File > > {
305
335
map_optional ( self . open ( path. as_ref ( ) ) )
@@ -452,6 +482,10 @@ impl CapStdExtDirExt for Dir {
452
482
Ok ( ( ) )
453
483
} )
454
484
}
485
+
486
+ fn is_mountpoint ( & self , path : impl AsRef < Path > ) -> Result < Option < bool > > {
487
+ is_mountpoint_impl_statx ( self , path. as_ref ( ) ) . map_err ( Into :: into)
488
+ }
455
489
}
456
490
457
491
// Implementation for the Utf8 variant of Dir. You shouldn't need to add
0 commit comments