77
88use clap:: builder:: ValueParser ;
99use clap:: { Arg , ArgAction , Command } ;
10- use std:: ffi:: OsString ;
10+ use std:: ffi:: { OsStr , OsString } ;
1111use uucore:: checksum:: compute:: {
1212 ChecksumComputeOptions , figure_out_output_format, perform_checksum_computation,
1313} ;
@@ -73,6 +73,42 @@ mod options {
7373/// Returns a pair of boolean. The first one indicates if we should use tagged
7474/// output format, the second one indicates if we should use the binary flag in
7575/// the untagged case.
76+ fn handle_tag_text_binary_flags < S : AsRef < OsStr > > (
77+ args : impl Iterator < Item = S > ,
78+ ) -> UResult < ( bool , bool ) > {
79+ let mut tag = true ;
80+ let mut binary = false ;
81+ let mut text = false ;
82+
83+ // --binary, --tag and --untagged are tight together: none of them
84+ // conflicts with each other but --tag will reset "binary" and "text" and
85+ // set "tag".
86+
87+ for arg in args {
88+ let arg = arg. as_ref ( ) ;
89+ if arg == "-b" || arg == "--binary" {
90+ text = false ;
91+ binary = true ;
92+ } else if arg == "--text" {
93+ text = true ;
94+ binary = false ;
95+ } else if arg == "--tag" {
96+ tag = true ;
97+ binary = false ;
98+ text = false ;
99+ } else if arg == "--untagged" {
100+ tag = false ;
101+ }
102+ }
103+
104+ // Specifying --text without ever mentioning --untagged fails.
105+ if text && tag {
106+ return Err ( ChecksumError :: TextWithoutUntagged . into ( ) ) ;
107+ }
108+
109+ Ok ( ( tag, binary) )
110+ }
111+
76112/// Sanitize the `--length` argument depending on `--algorithm` and `--length`.
77113fn maybe_sanitize_length (
78114 algo_cli : Option < AlgoKind > ,
@@ -103,11 +139,19 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
103139
104140 let check = matches. get_flag ( options:: CHECK ) ;
105141
106- let ignore_missing = matches. get_flag ( options:: IGNORE_MISSING ) ;
107- let warn = matches. get_flag ( options:: WARN ) ;
108- let quiet = matches. get_flag ( options:: QUIET ) ;
109- let strict = matches. get_flag ( options:: STRICT ) ;
110- let status = matches. get_flag ( options:: STATUS ) ;
142+ let check_flag = |flag| match ( check, matches. get_flag ( flag) ) {
143+ ( _, false ) => Ok ( false ) ,
144+ ( true , true ) => Ok ( true ) ,
145+ ( false , true ) => Err ( ChecksumError :: CheckOnlyFlag ( flag. into ( ) ) ) ,
146+ } ;
147+
148+ // Each of the following flags are only expected in --check mode.
149+ // If we encounter them otherwise, end with an error.
150+ let ignore_missing = check_flag ( options:: IGNORE_MISSING ) ?;
151+ let warn = check_flag ( options:: WARN ) ?;
152+ let quiet = check_flag ( options:: QUIET ) ?;
153+ let strict = check_flag ( options:: STRICT ) ?;
154+ let status = check_flag ( options:: STATUS ) ?;
111155
112156 let algo_cli = matches
113157 . get_one :: < String > ( options:: ALGORITHM )
@@ -132,6 +176,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
132176 return Err ( ChecksumError :: AlgorithmNotSupportedWithCheck . into ( ) ) ;
133177 }
134178
179+ let text_flag = matches. get_flag ( options:: TEXT ) ;
180+ let binary_flag = matches. get_flag ( options:: BINARY ) ;
181+ let tag = matches. get_flag ( options:: TAG ) ;
182+
183+ if tag || binary_flag || text_flag {
184+ return Err ( ChecksumError :: BinaryTextConflict . into ( ) ) ;
185+ }
186+
135187 // Execute the checksum validation based on the presence of files or the use of stdin
136188
137189 let verbose = ChecksumVerbose :: new ( status, quiet, warn) ;
@@ -154,8 +206,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
154206 // Set the default algorithm to CRC when not '--check'ing.
155207 let algo_kind = algo_cli. unwrap_or ( AlgoKind :: Crc ) ;
156208
157- let tag = !matches. get_flag ( options:: UNTAGGED ) ; // Making TAG default at clap blocks --untagged
158- let binary = matches. get_flag ( options:: BINARY ) ;
209+ let ( tag, binary) = handle_tag_text_binary_flags ( std:: env:: args_os ( ) ) ?;
159210
160211 let algo = SizedAlgoKind :: from_unsized ( algo_kind, length) ?;
161212 let line_ending = LineEnding :: from_zero_flag ( matches. get_flag ( options:: ZERO ) ) ;
@@ -214,9 +265,7 @@ pub fn uu_app() -> Command {
214265 . long ( options:: TAG )
215266 . help ( translate ! ( "cksum-help-tag" ) )
216267 . action ( ArgAction :: SetTrue )
217- . overrides_with ( options:: UNTAGGED )
218- . overrides_with ( options:: BINARY )
219- . overrides_with ( options:: TEXT ) ,
268+ . overrides_with ( options:: UNTAGGED ) ,
220269 )
221270 . arg (
222271 Arg :: new ( options:: LENGTH )
@@ -235,17 +284,13 @@ pub fn uu_app() -> Command {
235284 Arg :: new ( options:: STRICT )
236285 . long ( options:: STRICT )
237286 . help ( translate ! ( "cksum-help-strict" ) )
238- . action ( ArgAction :: SetTrue )
239- . requires ( options:: CHECK ) ,
287+ . action ( ArgAction :: SetTrue ) ,
240288 )
241289 . arg (
242290 Arg :: new ( options:: CHECK )
243291 . short ( 'c' )
244292 . long ( options:: CHECK )
245293 . help ( translate ! ( "cksum-help-check" ) )
246- . conflicts_with ( options:: TAG )
247- . conflicts_with ( options:: BINARY )
248- . conflicts_with ( options:: TEXT )
249294 . action ( ArgAction :: SetTrue ) ,
250295 )
251296 . arg (
@@ -263,8 +308,7 @@ pub fn uu_app() -> Command {
263308 . short ( 't' )
264309 . hide ( true )
265310 . overrides_with ( options:: BINARY )
266- . action ( ArgAction :: SetTrue )
267- . requires ( options:: UNTAGGED ) ,
311+ . action ( ArgAction :: SetTrue ) ,
268312 )
269313 . arg (
270314 Arg :: new ( options:: BINARY )
@@ -280,31 +324,27 @@ pub fn uu_app() -> Command {
280324 . long ( "warn" )
281325 . help ( translate ! ( "cksum-help-warn" ) )
282326 . action ( ArgAction :: SetTrue )
283- . overrides_with_all ( [ options:: STATUS , options:: QUIET ] )
284- . requires ( options:: CHECK ) ,
327+ . overrides_with_all ( [ options:: STATUS , options:: QUIET ] ) ,
285328 )
286329 . arg (
287330 Arg :: new ( options:: STATUS )
288331 . long ( "status" )
289332 . help ( translate ! ( "cksum-help-status" ) )
290333 . action ( ArgAction :: SetTrue )
291- . overrides_with_all ( [ options:: WARN , options:: QUIET ] )
292- . requires ( options:: CHECK ) ,
334+ . overrides_with_all ( [ options:: WARN , options:: QUIET ] ) ,
293335 )
294336 . arg (
295337 Arg :: new ( options:: QUIET )
296338 . long ( options:: QUIET )
297339 . help ( translate ! ( "cksum-help-quiet" ) )
298340 . action ( ArgAction :: SetTrue )
299- . overrides_with_all ( [ options:: WARN , options:: STATUS ] )
300- . requires ( options:: CHECK ) ,
341+ . overrides_with_all ( [ options:: WARN , options:: STATUS ] ) ,
301342 )
302343 . arg (
303344 Arg :: new ( options:: IGNORE_MISSING )
304345 . long ( options:: IGNORE_MISSING )
305346 . help ( translate ! ( "cksum-help-ignore-missing" ) )
306- . action ( ArgAction :: SetTrue )
307- . requires ( options:: CHECK ) ,
347+ . action ( ArgAction :: SetTrue ) ,
308348 )
309349 . arg (
310350 Arg :: new ( options:: ZERO )
0 commit comments