@@ -7,11 +7,60 @@ use std::io;
7
7
use std:: mem:: MaybeUninit ;
8
8
use std:: os:: unix:: io:: AsRawFd ;
9
9
10
- mod file_status;
11
- use crate :: oslib;
12
- use file_status:: { statx_st, STATX_BASIC_STATS , STATX_MNT_ID } ;
10
+ use super :: FileHandle ;
11
+ use crate :: api:: EMPTY_CSTR ;
12
+
13
+ #[ cfg( target_env = "gnu" ) ]
14
+ pub use libc:: statx as statx_st;
15
+
16
+ #[ cfg( target_env = "gnu" ) ]
17
+ pub use libc:: { STATX_BASIC_STATS , STATX_MNT_ID } ;
18
+
19
+ // musl provides the 'struct statx', but without stx_mnt_id.
20
+ // However, the libc crate does not provide libc::statx
21
+ // if musl is used. So we add just the required struct and
22
+ // constants to make it works.
23
+ #[ cfg( not( target_env = "gnu" ) ) ]
24
+ #[ repr( C ) ]
25
+ pub struct statx_st_timestamp {
26
+ pub tv_sec : i64 ,
27
+ pub tv_nsec : u32 ,
28
+ pub __statx_timestamp_pad1 : [ i32 ; 1 ] ,
29
+ }
30
+
31
+ #[ cfg( not( target_env = "gnu" ) ) ]
32
+ #[ repr( C ) ]
33
+ pub struct statx_st {
34
+ pub stx_mask : u32 ,
35
+ pub stx_blksize : u32 ,
36
+ pub stx_attributes : u64 ,
37
+ pub stx_nlink : u32 ,
38
+ pub stx_uid : u32 ,
39
+ pub stx_gid : u32 ,
40
+ pub stx_mode : u16 ,
41
+ __statx_pad1 : [ u16 ; 1 ] ,
42
+ pub stx_ino : u64 ,
43
+ pub stx_size : u64 ,
44
+ pub stx_blocks : u64 ,
45
+ pub stx_attributes_mask : u64 ,
46
+ pub stx_atime : statx_st_timestamp ,
47
+ pub stx_btime : statx_st_timestamp ,
48
+ pub stx_ctime : statx_st_timestamp ,
49
+ pub stx_mtime : statx_st_timestamp ,
50
+ pub stx_rdev_major : u32 ,
51
+ pub stx_rdev_minor : u32 ,
52
+ pub stx_dev_major : u32 ,
53
+ pub stx_dev_minor : u32 ,
54
+ pub stx_mnt_id : u64 ,
55
+ __statx_pad2 : u64 ,
56
+ __statx_pad3 : [ u64 ; 12 ] ,
57
+ }
13
58
14
- const EMPTY_CSTR : & [ u8 ] = b"\0 " ;
59
+ #[ cfg( not( target_env = "gnu" ) ) ]
60
+ pub const STATX_BASIC_STATS : libc:: c_uint = 0x07ff ;
61
+
62
+ #[ cfg( not( target_env = "gnu" ) ) ]
63
+ pub const STATX_MNT_ID : libc:: c_uint = 0x1000 ;
15
64
16
65
pub type MountId = u64 ;
17
66
@@ -84,12 +133,9 @@ impl SafeStatXAccess for statx_st {
84
133
}
85
134
86
135
fn get_mount_id ( dir : & impl AsRawFd , path : & CStr ) -> Option < MountId > {
87
- let mut mount_id: libc:: c_int = 0 ;
88
- let mut c_fh = oslib:: CFileHandle :: default ( ) ;
89
-
90
- oslib:: name_to_handle_at ( dir, path, & mut c_fh, & mut mount_id, libc:: AT_EMPTY_PATH )
136
+ FileHandle :: from_name_at ( dir. as_raw_fd ( ) , path)
137
+ . map ( |v| v. mnt_id )
91
138
. ok ( )
92
- . and ( Some ( mount_id as MountId ) )
93
139
}
94
140
95
141
// Only works on Linux, and libc::SYS_statx is only defined for these
@@ -109,7 +155,7 @@ unsafe fn do_statx(
109
155
libc:: syscall ( libc:: SYS_statx , dirfd, pathname, flags, mask, statxbuf) as libc:: c_int
110
156
}
111
157
112
- // Real statx() that depends on do_statx()
158
+ /// Execute ` statx()` to get extended status with mount id.
113
159
pub fn statx ( dir : & impl AsRawFd , path : Option < & CStr > ) -> io:: Result < StatExt > {
114
160
let mut stx_ui = MaybeUninit :: < statx_st > :: zeroed ( ) ;
115
161
@@ -138,13 +184,11 @@ pub fn statx(dir: &impl AsRawFd, path: Option<&CStr>) -> io::Result<StatExt> {
138
184
. mount_id ( )
139
185
. or_else ( || get_mount_id ( dir, path) )
140
186
. unwrap_or ( 0 ) ;
187
+ let st = stx
188
+ . stat64 ( )
189
+ . ok_or_else ( || io:: Error :: from_raw_os_error ( libc:: ENOSYS ) ) ?;
141
190
142
- Ok ( StatExt {
143
- st : stx
144
- . stat64 ( )
145
- . ok_or_else ( || io:: Error :: from_raw_os_error ( libc:: ENOSYS ) ) ?,
146
- mnt_id,
147
- } )
191
+ Ok ( StatExt { st, mnt_id } )
148
192
} else {
149
193
Err ( io:: Error :: last_os_error ( ) )
150
194
}
0 commit comments