55
66// spell-checker:ignore (ToDO) fullname
77
8+ use clap:: builder:: ValueParser ;
89use clap:: { Arg , ArgAction , Command } ;
910use std:: collections:: HashMap ;
11+ use std:: ffi:: OsString ;
12+ use std:: io:: { Write , stdout} ;
1013use std:: path:: PathBuf ;
1114use uucore:: display:: Quotable ;
1215use uucore:: error:: { UResult , UUsageError } ;
@@ -24,8 +27,6 @@ pub mod options {
2427
2528#[ uucore:: main]
2629pub fn uumain ( args : impl uucore:: Args ) -> UResult < ( ) > {
27- let args = args. collect_lossy ( ) ;
28-
2930 //
3031 // Argument parsing
3132 //
@@ -34,7 +35,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
3435 let line_ending = LineEnding :: from_zero_flag ( matches. get_flag ( options:: ZERO ) ) ;
3536
3637 let mut name_args = matches
37- . get_many :: < String > ( options:: NAME )
38+ . get_many :: < OsString > ( options:: NAME )
3839 . unwrap_or_default ( )
3940 . collect :: < Vec < _ > > ( ) ;
4041 if name_args. is_empty ( ) {
@@ -43,18 +44,18 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
4344 get_message ( "basename-error-missing-operand" ) ,
4445 ) ) ;
4546 }
46- let multiple_paths =
47- matches . get_one :: < String > ( options :: SUFFIX ) . is_some ( ) || matches. get_flag ( options:: MULTIPLE ) ;
47+ let multiple_paths = matches . get_one :: < OsString > ( options :: SUFFIX ) . is_some ( )
48+ || matches. get_flag ( options:: MULTIPLE ) ;
4849 let suffix = if multiple_paths {
4950 matches
50- . get_one :: < String > ( options:: SUFFIX )
51+ . get_one :: < OsString > ( options:: SUFFIX )
5152 . cloned ( )
5253 . unwrap_or_default ( )
5354 } else {
5455 // "simple format"
5556 match name_args. len ( ) {
5657 0 => panic ! ( "already checked" ) ,
57- 1 => String :: default ( ) ,
58+ 1 => OsString :: default ( ) ,
5859 2 => name_args. pop ( ) . unwrap ( ) . clone ( ) ,
5960 _ => {
6061 return Err ( UUsageError :: new (
@@ -73,7 +74,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
7374 //
7475
7576 for path in name_args {
76- print ! ( "{}{line_ending}" , basename( path, & suffix) ) ;
77+ stdout ( ) . write_all ( & basename ( path, & suffix) ?) ?;
78+ print ! ( "{line_ending}" ) ;
7779 }
7880
7981 Ok ( ( ) )
@@ -96,6 +98,7 @@ pub fn uu_app() -> Command {
9698 . arg (
9799 Arg :: new ( options:: NAME )
98100 . action ( ArgAction :: Append )
101+ . value_parser ( ValueParser :: os_string ( ) )
99102 . value_hint ( clap:: ValueHint :: AnyPath )
100103 . hide ( true )
101104 . trailing_var_arg ( true ) ,
@@ -105,6 +108,7 @@ pub fn uu_app() -> Command {
105108 . short ( 's' )
106109 . long ( options:: SUFFIX )
107110 . value_name ( "SUFFIX" )
111+ . value_parser ( ValueParser :: os_string ( ) )
108112 . help ( get_message ( "basename-help-suffix" ) )
109113 . overrides_with ( options:: SUFFIX ) ,
110114 )
@@ -118,21 +122,30 @@ pub fn uu_app() -> Command {
118122 )
119123}
120124
121- fn basename ( fullname : & str , suffix : & str ) -> String {
125+ // We return a Vec<u8>. Returning a seemingly more proper `OsString` would
126+ // require back and forth conversions as we need a &[u8] for printing anyway.
127+ fn basename ( fullname : & OsString , suffix : & OsString ) -> UResult < Vec < u8 > > {
128+ let fullname_bytes = uucore:: os_str_as_bytes ( fullname) ?;
129+
122130 // Handle special case where path ends with /.
123- if fullname . ends_with ( "/." ) {
124- return "." . to_string ( ) ;
131+ if fullname_bytes . ends_with ( b "/.") {
132+ return Ok ( b ".". into ( ) ) ;
125133 }
126134
127135 // Convert to path buffer and get last path component
128136 let pb = PathBuf :: from ( fullname) ;
129137
130- pb. components ( ) . next_back ( ) . map_or_else ( String :: new, |c| {
131- let name = c. as_os_str ( ) . to_str ( ) . unwrap ( ) ;
138+ pb. components ( ) . next_back ( ) . map_or ( Ok ( [ ] . into ( ) ) , |c| {
139+ let name = c. as_os_str ( ) ;
140+ let name_bytes = uucore:: os_str_as_bytes ( name) ?;
132141 if name == suffix {
133- name . to_string ( )
142+ Ok ( name_bytes . into ( ) )
134143 } else {
135- name. strip_suffix ( suffix) . unwrap_or ( name) . to_string ( )
144+ let suffix_bytes = uucore:: os_str_as_bytes ( suffix) ?;
145+ Ok ( name_bytes
146+ . strip_suffix ( suffix_bytes)
147+ . unwrap_or ( name_bytes)
148+ . into ( ) )
136149 }
137150 } )
138151}
0 commit comments