55
66// spell-checker:ignore (ToDO) RFILE refsize rfilename fsize tsize
77use clap:: { Arg , ArgAction , Command } ;
8+ use std:: collections:: HashMap ;
89use std:: fs:: { OpenOptions , metadata} ;
910use std:: io:: ErrorKind ;
1011#[ cfg( unix) ]
@@ -13,7 +14,7 @@ use std::path::Path;
1314use uucore:: display:: Quotable ;
1415use uucore:: error:: { FromIo , UResult , USimpleError , UUsageError } ;
1516use uucore:: format_usage;
16- use uucore:: locale:: get_message;
17+ use uucore:: locale:: { get_message, get_message_with_args } ;
1718use uucore:: parser:: parse_size:: { ParseSizeError , parse_size_u64} ;
1819
1920#[ derive( Debug , Eq , PartialEq ) ]
@@ -99,7 +100,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
99100 . unwrap_or_default ( ) ;
100101
101102 if files. is_empty ( ) {
102- Err ( UUsageError :: new ( 1 , "missing file operand" ) )
103+ Err ( UUsageError :: new (
104+ 1 ,
105+ get_message ( "truncate-error-missing-file-operand" ) ,
106+ ) )
103107 } else {
104108 let io_blocks = matches. get_flag ( options:: IO_BLOCKS ) ;
105109 let no_create = matches. get_flag ( options:: NO_CREATE ) ;
@@ -121,25 +125,22 @@ pub fn uu_app() -> Command {
121125 Arg :: new ( options:: IO_BLOCKS )
122126 . short ( 'o' )
123127 . long ( options:: IO_BLOCKS )
124- . help (
125- "treat SIZE as the number of I/O blocks of the file rather than bytes \
126- (NOT IMPLEMENTED)",
127- )
128+ . help ( get_message ( "truncate-help-io-blocks" ) )
128129 . action ( ArgAction :: SetTrue ) ,
129130 )
130131 . arg (
131132 Arg :: new ( options:: NO_CREATE )
132133 . short ( 'c' )
133134 . long ( options:: NO_CREATE )
134- . help ( "do not create files that do not exist" )
135+ . help ( get_message ( "truncate-help-no- create" ) )
135136 . action ( ArgAction :: SetTrue ) ,
136137 )
137138 . arg (
138139 Arg :: new ( options:: REFERENCE )
139140 . short ( 'r' )
140141 . long ( options:: REFERENCE )
141142 . required_unless_present ( options:: SIZE )
142- . help ( "base the size of each file on the size of RFILE" )
143+ . help ( get_message ( "truncate-help-reference" ) )
143144 . value_name ( "RFILE" )
144145 . value_hint ( clap:: ValueHint :: FilePath ) ,
145146 )
@@ -148,10 +149,7 @@ pub fn uu_app() -> Command {
148149 . short ( 's' )
149150 . long ( options:: SIZE )
150151 . required_unless_present ( options:: REFERENCE )
151- . help (
152- "set or adjust the size of each file according to SIZE, which is in \
153- bytes unless --io-blocks is specified",
154- )
152+ . help ( get_message ( "truncate-help-size" ) )
155153 . value_name ( "SIZE" ) ,
156154 )
157155 . arg (
@@ -181,20 +179,26 @@ fn file_truncate(filename: &str, create: bool, size: u64) -> UResult<()> {
181179 if metadata. file_type ( ) . is_fifo ( ) {
182180 return Err ( USimpleError :: new (
183181 1 ,
184- format ! (
185- "cannot open {} for writing: No such device or address " ,
186- filename. quote( )
182+ get_message_with_args (
183+ "truncate-error- cannot- open-no- device" ,
184+ HashMap :: from ( [ ( " filename" . to_string ( ) , filename . quote ( ) . to_string ( ) ) ] ) ,
187185 ) ,
188186 ) ) ;
189187 }
190188 }
189+
191190 let path = Path :: new ( filename) ;
192191 match OpenOptions :: new ( ) . write ( true ) . create ( create) . open ( path) {
193192 Ok ( file) => file. set_len ( size) ,
194193 Err ( e) if e. kind ( ) == ErrorKind :: NotFound && !create => Ok ( ( ) ) ,
195194 Err ( e) => Err ( e) ,
196195 }
197- . map_err_context ( || format ! ( "cannot open {} for writing" , filename. quote( ) ) )
196+ . map_err_context ( || {
197+ get_message_with_args (
198+ "truncate-error-cannot-open-for-writing" ,
199+ HashMap :: from ( [ ( "filename" . to_string ( ) , filename. quote ( ) . to_string ( ) ) ] ) ,
200+ )
201+ } )
198202}
199203
200204/// Truncate files to a size relative to a given file.
@@ -221,33 +225,49 @@ fn truncate_reference_and_size(
221225 create : bool ,
222226) -> UResult < ( ) > {
223227 let mode = match parse_mode_and_size ( size_string) {
224- Err ( e) => return Err ( USimpleError :: new ( 1 , format ! ( "Invalid number: {e}" ) ) ) ,
228+ Err ( e) => {
229+ return Err ( USimpleError :: new (
230+ 1 ,
231+ get_message_with_args (
232+ "truncate-error-invalid-number" ,
233+ HashMap :: from ( [ ( "error" . to_string ( ) , e. to_string ( ) ) ] ) ,
234+ ) ,
235+ ) ) ;
236+ }
225237 Ok ( TruncateMode :: Absolute ( _) ) => {
226238 return Err ( USimpleError :: new (
227239 1 ,
228- String :: from ( "you must specify a relative '-- size' with '--reference' ") ,
240+ get_message ( "truncate-error- must- specify- relative- size") ,
229241 ) ) ;
230242 }
231243 Ok ( m) => m,
232244 } ;
245+
233246 if let TruncateMode :: RoundDown ( 0 ) | TruncateMode :: RoundUp ( 0 ) = mode {
234- return Err ( USimpleError :: new ( 1 , "division by zero" ) ) ;
247+ return Err ( USimpleError :: new (
248+ 1 ,
249+ get_message ( "truncate-error-division-by-zero" ) ,
250+ ) ) ;
235251 }
252+
236253 let metadata = metadata ( rfilename) . map_err ( |e| match e. kind ( ) {
237254 ErrorKind :: NotFound => USimpleError :: new (
238255 1 ,
239- format ! (
240- "cannot stat {}: No such file or directory " ,
241- rfilename. quote( )
256+ get_message_with_args (
257+ "truncate-error- cannot- stat-no- such- file" ,
258+ HashMap :: from ( [ ( "filename" . to_string ( ) , rfilename. quote ( ) . to_string ( ) ) ] ) ,
242259 ) ,
243260 ) ,
244261 _ => e. map_err_context ( String :: new) ,
245262 } ) ?;
263+
246264 let fsize = metadata. len ( ) ;
247265 let tsize = mode. to_size ( fsize) ;
266+
248267 for filename in filenames {
249268 file_truncate ( filename, create, tsize) ?;
250269 }
270+
251271 Ok ( ( ) )
252272}
253273
@@ -272,17 +292,20 @@ fn truncate_reference_file_only(
272292 let metadata = metadata ( rfilename) . map_err ( |e| match e. kind ( ) {
273293 ErrorKind :: NotFound => USimpleError :: new (
274294 1 ,
275- format ! (
276- "cannot stat {}: No such file or directory " ,
277- rfilename. quote( )
295+ get_message_with_args (
296+ "truncate-error- cannot- stat-no- such- file" ,
297+ HashMap :: from ( [ ( "filename" . to_string ( ) , rfilename. quote ( ) . to_string ( ) ) ] ) ,
278298 ) ,
279299 ) ,
280300 _ => e. map_err_context ( String :: new) ,
281301 } ) ?;
302+
282303 let tsize = metadata. len ( ) ;
304+
283305 for filename in filenames {
284306 file_truncate ( filename, create, tsize) ?;
285307 }
308+
286309 Ok ( ( ) )
287310}
288311
@@ -304,21 +327,33 @@ fn truncate_reference_file_only(
304327///
305328/// If at least one file is a named pipe (also known as a fifo).
306329fn truncate_size_only ( size_string : & str , filenames : & [ String ] , create : bool ) -> UResult < ( ) > {
307- let mode = parse_mode_and_size ( size_string)
308- . map_err ( |e| USimpleError :: new ( 1 , format ! ( "Invalid number: {e}" ) ) ) ?;
330+ let mode = parse_mode_and_size ( size_string) . map_err ( |e| {
331+ USimpleError :: new (
332+ 1 ,
333+ get_message_with_args (
334+ "truncate-error-invalid-number" ,
335+ HashMap :: from ( [ ( "error" . to_string ( ) , e. to_string ( ) ) ] ) ,
336+ ) ,
337+ )
338+ } ) ?;
339+
309340 if let TruncateMode :: RoundDown ( 0 ) | TruncateMode :: RoundUp ( 0 ) = mode {
310- return Err ( USimpleError :: new ( 1 , "division by zero" ) ) ;
341+ return Err ( USimpleError :: new (
342+ 1 ,
343+ get_message ( "truncate-error-division-by-zero" ) ,
344+ ) ) ;
311345 }
346+
312347 for filename in filenames {
313348 let fsize = match metadata ( filename) {
314349 Ok ( m) => {
315350 #[ cfg( unix) ]
316351 if m. file_type ( ) . is_fifo ( ) {
317352 return Err ( USimpleError :: new (
318353 1 ,
319- format ! (
320- "cannot open {} for writing: No such device or address " ,
321- filename. quote( )
354+ get_message_with_args (
355+ "truncate-error- cannot- open-no- device" ,
356+ HashMap :: from ( [ ( " filename" . to_string ( ) , filename . quote ( ) . to_string ( ) ) ] ) ,
322357 ) ,
323358 ) ) ;
324359 }
@@ -330,6 +365,7 @@ fn truncate_size_only(size_string: &str, filenames: &[String], create: bool) ->
330365 // TODO: Fix duplicate call to stat
331366 file_truncate ( filename, create, tsize) ?;
332367 }
368+
333369 Ok ( ( ) )
334370}
335371
@@ -341,6 +377,7 @@ fn truncate(
341377 filenames : & [ String ] ,
342378) -> UResult < ( ) > {
343379 let create = !no_create;
380+
344381 // There are four possibilities
345382 // - reference file given and size given,
346383 // - reference file given but no size given,
0 commit comments