@@ -9,7 +9,7 @@ use uucore::translate;
99
1010use clap:: builder:: ValueParser ;
1111use uucore:: display:: Quotable ;
12- use uucore:: fs:: display_permissions;
12+ use uucore:: fs:: { display_permissions, major , minor } ;
1313use uucore:: fsext:: {
1414 FsMeta , MetadataTimeField , StatFs , metadata_get_time, pretty_filetype, pretty_fstype,
1515 read_fs_list, statfs,
@@ -70,6 +70,8 @@ struct Flags {
7070 space : bool ,
7171 sign : bool ,
7272 group : bool ,
73+ major : bool ,
74+ minor : bool ,
7375}
7476
7577/// checks if the string is within the specified bound,
@@ -739,7 +741,6 @@ impl Stater {
739741 return Ok ( Token :: Char ( '%' ) ) ;
740742 }
741743 if chars[ * i] == '%' {
742- * i += 1 ;
743744 return Ok ( Token :: Char ( '%' ) ) ;
744745 }
745746
@@ -794,13 +795,14 @@ impl Stater {
794795 if let Some ( & next_char) = chars. get ( * i + 1 ) {
795796 if ( chars[ * i] == 'H' || chars[ * i] == 'L' ) && ( next_char == 'd' || next_char == 'r' )
796797 {
797- let specifier = format ! ( "{}{next_char}" , chars[ * i] ) ;
798+ flag. major = chars[ * i] == 'H' ;
799+ flag. minor = chars[ * i] == 'L' ;
798800 * i += 1 ;
799801 return Ok ( Token :: Directive {
800802 flag,
801803 width,
802804 precision,
803- format : specifier . chars ( ) . next ( ) . unwrap ( ) ,
805+ format : next_char ,
804806 } ) ;
805807 }
806808 }
@@ -908,6 +910,28 @@ impl Stater {
908910 Ok ( tokens)
909911 }
910912
913+ fn populate_mount_list ( ) -> UResult < Vec < OsString > > {
914+ let mut mount_list = read_fs_list ( )
915+ . map_err ( |e| {
916+ USimpleError :: new (
917+ e. code ( ) ,
918+ StatError :: CannotReadFilesystem {
919+ error : e. to_string ( ) ,
920+ }
921+ . to_string ( ) ,
922+ )
923+ } ) ?
924+ . iter ( )
925+ . map ( |mi| mi. mount_dir . clone ( ) )
926+ . collect :: < Vec < _ > > ( ) ;
927+
928+ // Reverse sort. The longer comes first.
929+ mount_list. sort ( ) ;
930+ mount_list. reverse ( ) ;
931+
932+ Ok ( mount_list)
933+ }
934+
911935 fn new ( matches : & ArgMatches ) -> UResult < Self > {
912936 let files: Vec < OsString > = matches
913937 . get_many :: < OsString > ( options:: FILES )
@@ -938,27 +962,16 @@ impl Stater {
938962 let default_dev_tokens =
939963 Self :: generate_tokens ( & Self :: default_format ( show_fs, terse, true ) , use_printf) ?;
940964
941- let mount_list = if show_fs {
942- // mount points aren't displayed when showing filesystem information
965+ // mount points aren't displayed when showing filesystem information, or
966+ // whenever the format string does not request the mount point.
967+ let mount_list = if show_fs
968+ || !default_tokens
969+ . iter ( )
970+ . any ( |tok| matches ! ( tok, Token :: Directive { format: 'm' , .. } ) )
971+ {
943972 None
944973 } else {
945- let mut mount_list = read_fs_list ( )
946- . map_err ( |e| {
947- USimpleError :: new (
948- e. code ( ) ,
949- StatError :: CannotReadFilesystem {
950- error : e. to_string ( ) ,
951- }
952- . to_string ( ) ,
953- )
954- } ) ?
955- . iter ( )
956- . map ( |mi| mi. mount_dir . clone ( ) )
957- . collect :: < Vec < _ > > ( ) ;
958- // Reverse sort. The longer comes first.
959- mount_list. sort ( ) ;
960- mount_list. reverse ( ) ;
961- Some ( mount_list)
974+ Some ( Self :: populate_mount_list ( ) ?)
962975 } ;
963976
964977 Ok ( Self {
@@ -1052,6 +1065,8 @@ impl Stater {
10521065 }
10531066 }
10541067 // device number in decimal
1068+ 'd' if flag. major => OutputType :: Unsigned ( major ( meta. dev ( ) as _ ) as u64 ) ,
1069+ 'd' if flag. minor => OutputType :: Unsigned ( minor ( meta. dev ( ) as _ ) as u64 ) ,
10551070 'd' => OutputType :: Unsigned ( meta. dev ( ) ) ,
10561071 // device number in hex
10571072 'D' => OutputType :: UnsignedHex ( meta. dev ( ) ) ,
@@ -1090,10 +1105,10 @@ impl Stater {
10901105 's' => OutputType :: Integer ( meta. len ( ) as i64 ) ,
10911106 // major device type in hex, for character/block device special
10921107 // files
1093- 't' => OutputType :: UnsignedHex ( meta. rdev ( ) >> 8 ) ,
1108+ 't' => OutputType :: UnsignedHex ( major ( meta. rdev ( ) as _ ) as u64 ) ,
10941109 // minor device type in hex, for character/block device special
10951110 // files
1096- 'T' => OutputType :: UnsignedHex ( meta. rdev ( ) & 0xff ) ,
1111+ 'T' => OutputType :: UnsignedHex ( minor ( meta. rdev ( ) as _ ) as u64 ) ,
10971112 // user ID of owner
10981113 'u' => OutputType :: Unsigned ( meta. uid ( ) as u64 ) ,
10991114 // user name of owner
@@ -1136,15 +1151,10 @@ impl Stater {
11361151 . map_or ( ( 0 , 0 ) , system_time_to_sec) ;
11371152 OutputType :: Float ( sec as f64 + nsec as f64 / 1_000_000_000.0 )
11381153 }
1139- 'R' => {
1140- let major = meta. rdev ( ) >> 8 ;
1141- let minor = meta. rdev ( ) & 0xff ;
1142- OutputType :: Str ( format ! ( "{major},{minor}" ) )
1143- }
1154+ 'R' => OutputType :: UnsignedHex ( meta. rdev ( ) ) ,
1155+ 'r' if flag. major => OutputType :: Unsigned ( major ( meta. rdev ( ) as _ ) as u64 ) ,
1156+ 'r' if flag. minor => OutputType :: Unsigned ( minor ( meta. rdev ( ) as _ ) as u64 ) ,
11441157 'r' => OutputType :: Unsigned ( meta. rdev ( ) ) ,
1145- 'H' => OutputType :: Unsigned ( meta. rdev ( ) >> 8 ) , // Major in decimal
1146- 'L' => OutputType :: Unsigned ( meta. rdev ( ) & 0xff ) , // Minor in decimal
1147-
11481158 _ => OutputType :: Unknown ,
11491159 } ;
11501160 print_it ( & output, flag, width, precision) ;
@@ -1269,7 +1279,7 @@ impl Stater {
12691279 } else {
12701280 let device_line = if show_dev_type {
12711281 format ! (
1272- "{}: %Dh/%dd \t {}: %-10i {}: %-5h {} {}: %t,%T\n " ,
1282+ "{}: %Hd,%Ld \t {}: %-10i {}: %-5h {} {}: %t,%T\n " ,
12731283 translate!( "stat-word-device" ) ,
12741284 translate!( "stat-word-inode" ) ,
12751285 translate!( "stat-word-links" ) ,
@@ -1278,7 +1288,7 @@ impl Stater {
12781288 )
12791289 } else {
12801290 format ! (
1281- "{}: %Dh/%dd \t {}: %-10i {}: %h\n " ,
1291+ "{}: %Hd,%Ld \t {}: %-10i {}: %h\n " ,
12821292 translate!( "stat-word-device" ) ,
12831293 translate!( "stat-word-inode" ) ,
12841294 translate!( "stat-word-links" )
0 commit comments