@@ -25,7 +25,7 @@ use uucore::display::{Quotable, print_verbatim};
2525use uucore:: error:: { FromIo , UError , UResult , USimpleError , set_exit_code} ;
2626use uucore:: fsext:: { MetadataTimeField , metadata_get_time} ;
2727use uucore:: line_ending:: LineEnding ;
28- #[ cfg( target_os = "linux" ) ]
28+ #[ cfg( all ( unix , not ( target_os = "redox" ) ) ) ]
2929use uucore:: safe_traversal:: DirFd ;
3030use uucore:: translate;
3131
@@ -164,7 +164,7 @@ impl Stat {
164164 }
165165
166166 /// Create a Stat using safe traversal methods with `DirFd` for the root directory
167- #[ cfg( target_os = "linux" ) ]
167+ #[ cfg( all ( unix , not ( target_os = "redox" ) ) ) ]
168168 fn new_from_dirfd ( dir_fd : & DirFd , full_path : & Path ) -> std:: io:: Result < Self > {
169169 // Get metadata for the directory itself using fstat
170170 let safe_metadata = dir_fd. metadata ( ) ?;
@@ -293,9 +293,9 @@ fn read_block_size(s: Option<&str>) -> UResult<u64> {
293293 }
294294}
295295
296- #[ cfg( target_os = "linux" ) ]
297- // For now, implement safe_du only on Linux
298- // This is done for Ubuntu but should be extended to other platforms that support openat
296+ #[ cfg( all ( unix , not ( target_os = "redox" ) ) ) ]
297+ // Implement safe_du on Unix (except Redox which lacks full stat support)
298+ // This is done for TOCTOU safety
299299fn safe_du (
300300 path : & Path ,
301301 options : & TraversalOptions ,
@@ -439,7 +439,8 @@ fn safe_du(
439439 const S_IFMT : u32 = 0o170_000 ;
440440 const S_IFDIR : u32 = 0o040_000 ;
441441 const S_IFLNK : u32 = 0o120_000 ;
442- let is_symlink = ( lstat. st_mode & S_IFMT ) == S_IFLNK ;
442+ #[ allow( clippy:: unnecessary_cast) ]
443+ let is_symlink = ( lstat. st_mode as u32 & S_IFMT ) == S_IFLNK ;
443444
444445 // Handle symlinks with -L option
445446 // For safe traversal with -L, we skip symlinks to directories entirely
@@ -450,12 +451,14 @@ fn safe_du(
450451 continue ;
451452 }
452453
453- let is_dir = ( lstat. st_mode & S_IFMT ) == S_IFDIR ;
454+ #[ allow( clippy:: unnecessary_cast) ]
455+ let is_dir = ( lstat. st_mode as u32 & S_IFMT ) == S_IFDIR ;
454456 let entry_stat = lstat;
455457
458+ #[ allow( clippy:: unnecessary_cast) ]
456459 let file_info = ( entry_stat. st_ino != 0 ) . then_some ( FileInfo {
457460 file_id : entry_stat. st_ino as u128 ,
458- dev_id : entry_stat. st_dev ,
461+ dev_id : entry_stat. st_dev as u64 ,
459462 } ) ;
460463
461464 // For safe traversal, we need to handle stats differently
@@ -465,6 +468,7 @@ fn safe_du(
465468 Stat {
466469 path : entry_path. clone ( ) ,
467470 size : 0 ,
471+ #[ allow( clippy:: unnecessary_cast) ]
468472 blocks : entry_stat. st_blocks as u64 ,
469473 inodes : 1 ,
470474 inode : file_info,
@@ -476,7 +480,9 @@ fn safe_du(
476480 // For files
477481 Stat {
478482 path : entry_path. clone ( ) ,
483+ #[ allow( clippy:: unnecessary_cast) ]
479484 size : entry_stat. st_size as u64 ,
485+ #[ allow( clippy:: unnecessary_cast) ]
480486 blocks : entry_stat. st_blocks as u64 ,
481487 inodes : 1 ,
482488 inode : file_info,
@@ -1096,14 +1102,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
10961102 let mut seen_inodes: HashSet < FileInfo > = HashSet :: new ( ) ;
10971103
10981104 // Determine which traversal method to use
1099- #[ cfg( target_os = "linux" ) ]
1105+ #[ cfg( all ( unix , not ( target_os = "redox" ) ) ) ]
11001106 let use_safe_traversal = traversal_options. dereference != Deref :: All ;
1101- #[ cfg( not( target_os = "linux" ) ) ]
1107+ #[ cfg( not( all ( unix , not ( target_os = "redox" ) ) ) ) ]
11021108 let use_safe_traversal = false ;
11031109
11041110 if use_safe_traversal {
1105- // Use safe traversal (Linux only , when not using -L)
1106- #[ cfg( target_os = "linux" ) ]
1111+ // Use safe traversal (Unix except Redox , when not using -L)
1112+ #[ cfg( all ( unix , not ( target_os = "redox" ) ) ) ]
11071113 {
11081114 // Pre-populate seen_inodes with the starting directory to detect cycles
11091115 if let Ok ( stat) = Stat :: new ( & path, None , & traversal_options) {
@@ -1158,9 +1164,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
11581164 . send ( Ok ( StatPrintInfo { stat, depth : 0 } ) )
11591165 . map_err ( |e| USimpleError :: new ( 1 , e. to_string ( ) ) ) ?;
11601166 } else {
1161- #[ cfg( target_os = "linux" ) ]
1167+ #[ cfg( unix ) ]
11621168 let error_msg = translate ! ( "du-error-cannot-access" , "path" => path. quote( ) ) ;
1163- #[ cfg( not( target_os = "linux" ) ) ]
1169+ #[ cfg( not( unix ) ) ]
11641170 let error_msg =
11651171 translate ! ( "du-error-cannot-access-no-such-file" , "path" => path. quote( ) ) ;
11661172
0 commit comments