1010#[ cfg( target_os = "linux" ) ]
1111mod mntent;
1212
13+ #[ cfg( target_os = "linux" ) ]
14+ use crate :: mntent:: MountTable ;
15+
1316use clap:: Parser ;
1417use gettextrs:: { bind_textdomain_codeset, gettext, setlocale, textdomain, LocaleCategory } ;
1518use plib:: PROJECT_NAME ;
16- use std:: ffi:: { CStr , CString } ;
19+ #[ cfg( target_os = "macos" ) ]
20+ use std:: ffi:: CStr ;
21+ use std:: ffi:: CString ;
1722use std:: io;
1823
19- #[ cfg( target_os = "linux" ) ]
20- const _PATH_MOUNTED: & ' static str = "/etc/mtab" ;
21-
2224#[ derive( Parser ) ]
2325#[ command( version, about = gettext( "df - report free storage space" ) ) ]
2426struct Args {
@@ -57,9 +59,7 @@ fn to_cstr(array: &[libc::c_char]) -> &CStr {
5759 }
5860}
5961
60- fn stat ( filename_str : & str ) -> io:: Result < libc:: stat > {
61- let filename = CString :: new ( filename_str) . unwrap ( ) ;
62-
62+ fn stat ( filename : & CString ) -> io:: Result < libc:: stat > {
6363 unsafe {
6464 let mut st: libc:: stat = std:: mem:: zeroed ( ) ;
6565 let rc = libc:: stat ( filename. as_ptr ( ) , & mut st) ;
@@ -105,11 +105,11 @@ impl MountList {
105105 }
106106 }
107107
108- fn push ( & mut self , fsstat : & libc:: statfs , devname : & CStr , dirname : & CStr ) {
108+ fn push ( & mut self , fsstat : & libc:: statfs , devname : & CString , dirname : & CString ) {
109109 let dev = {
110- if let Ok ( st) = stat ( devname. to_str ( ) . unwrap ( ) ) {
110+ if let Ok ( st) = stat ( devname) {
111111 st. st_rdev as i64
112- } else if let Ok ( st) = stat ( dirname. to_str ( ) . unwrap ( ) ) {
112+ } else if let Ok ( st) = stat ( dirname) {
113113 st. st_dev as i64
114114 } else {
115115 -1
@@ -139,9 +139,9 @@ fn read_mount_info() -> io::Result<MountList> {
139139
140140 let mounts: & [ libc:: statfs ] = std:: slice:: from_raw_parts ( mounts as _ , n_mnt as _ ) ;
141141 for mount in mounts {
142- let devname = to_cstr ( & mount. f_mntfromname ) ;
143- let dirname = to_cstr ( & mount. f_mntonname ) ;
144- info. push ( mount, devname, dirname) ;
142+ let devname = to_cstr ( & mount. f_mntfromname ) . into ( ) ;
143+ let dirname = to_cstr ( & mount. f_mntonname ) . into ( ) ;
144+ info. push ( mount, & devname, & dirname) ;
145145 }
146146 }
147147
@@ -152,47 +152,30 @@ fn read_mount_info() -> io::Result<MountList> {
152152fn read_mount_info ( ) -> io:: Result < MountList > {
153153 let mut info = MountList :: new ( ) ;
154154
155- unsafe {
156- let path_mnt = CString :: new ( _PATH_MOUNTED) . unwrap ( ) ;
157- let mnt_mode = CString :: new ( "r" ) . unwrap ( ) ;
158- let f = libc:: setmntent ( path_mnt. as_ptr ( ) , mnt_mode. as_ptr ( ) ) ;
159- if f. is_null ( ) {
160- return Err ( io:: Error :: last_os_error ( ) ) ;
161- }
162-
163- loop {
164- let me = libc:: getmntent ( f) ;
165- if me. is_null ( ) {
166- break ;
167- }
168-
169- let me_devname = ( * me) . mnt_fsname ;
170- let me_dirname = ( * me) . mnt_dir ;
171- let devname = CStr :: from_ptr ( me_devname) ;
172- let dirname = CStr :: from_ptr ( me_dirname) ;
173-
174- let mut mount: libc:: statfs = std:: mem:: zeroed ( ) ;
175- let rc = libc:: statfs ( dirname. as_ptr ( ) , & mut mount) ;
155+ let mounts = MountTable :: try_new ( ) ?;
156+ for mount in mounts {
157+ unsafe {
158+ let mut buf: libc:: statfs = std:: mem:: zeroed ( ) ;
159+ let rc = libc:: statfs ( mount. dir . as_ptr ( ) , & mut buf) ;
176160 if rc < 0 {
177161 eprintln ! (
178162 "{}: {}" ,
179- dirname . to_str( ) . unwrap( ) ,
163+ mount . dir . to_str( ) . unwrap( ) ,
180164 io:: Error :: last_os_error( )
181165 ) ;
182166 continue ;
183167 }
184168
185- info. push ( & mount , devname , dirname ) ;
169+ info. push ( & buf , & mount . fsname , & mount . dir ) ;
186170 }
187-
188- libc:: endmntent ( f) ;
189171 }
190172
191173 Ok ( info)
192174}
193175
194176fn mask_fs_by_file ( info : & mut MountList , filename : & str ) -> io:: Result < ( ) > {
195- let stat_res = stat ( filename) ;
177+ let c_filename = CString :: new ( filename) . expect ( "`filename` contains an internal 0 byte" ) ;
178+ let stat_res = stat ( & c_filename) ;
196179 if let Err ( e) = stat_res {
197180 eprintln ! ( "{}: {}" , filename, e) ;
198181 return Err ( e) ;
0 commit comments