5
5
6
6
// spell-checker:ignore (ToDO) RFILE refsize rfilename fsize tsize
7
7
use clap:: { Arg , ArgAction , Command } ;
8
+ use std:: collections:: HashMap ;
8
9
use std:: fs:: { OpenOptions , metadata} ;
9
10
use std:: io:: ErrorKind ;
10
11
#[ cfg( unix) ]
@@ -13,7 +14,7 @@ use std::path::Path;
13
14
use uucore:: display:: Quotable ;
14
15
use uucore:: error:: { FromIo , UResult , USimpleError , UUsageError } ;
15
16
use uucore:: format_usage;
16
- use uucore:: locale:: get_message;
17
+ use uucore:: locale:: { get_message, get_message_with_args } ;
17
18
use uucore:: parser:: parse_size:: { ParseSizeError , parse_size_u64} ;
18
19
19
20
#[ derive( Debug , Eq , PartialEq ) ]
@@ -99,7 +100,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
99
100
. unwrap_or_default ( ) ;
100
101
101
102
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
+ ) )
103
107
} else {
104
108
let io_blocks = matches. get_flag ( options:: IO_BLOCKS ) ;
105
109
let no_create = matches. get_flag ( options:: NO_CREATE ) ;
@@ -121,25 +125,22 @@ pub fn uu_app() -> Command {
121
125
Arg :: new ( options:: IO_BLOCKS )
122
126
. short ( 'o' )
123
127
. 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" ) )
128
129
. action ( ArgAction :: SetTrue ) ,
129
130
)
130
131
. arg (
131
132
Arg :: new ( options:: NO_CREATE )
132
133
. short ( 'c' )
133
134
. long ( options:: NO_CREATE )
134
- . help ( "do not create files that do not exist" )
135
+ . help ( get_message ( "truncate-help-no- create" ) )
135
136
. action ( ArgAction :: SetTrue ) ,
136
137
)
137
138
. arg (
138
139
Arg :: new ( options:: REFERENCE )
139
140
. short ( 'r' )
140
141
. long ( options:: REFERENCE )
141
142
. 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" ) )
143
144
. value_name ( "RFILE" )
144
145
. value_hint ( clap:: ValueHint :: FilePath ) ,
145
146
)
@@ -148,10 +149,7 @@ pub fn uu_app() -> Command {
148
149
. short ( 's' )
149
150
. long ( options:: SIZE )
150
151
. 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" ) )
155
153
. value_name ( "SIZE" ) ,
156
154
)
157
155
. arg (
@@ -181,20 +179,26 @@ fn file_truncate(filename: &str, create: bool, size: u64) -> UResult<()> {
181
179
if metadata. file_type ( ) . is_fifo ( ) {
182
180
return Err ( USimpleError :: new (
183
181
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 ( ) ) ] ) ,
187
185
) ,
188
186
) ) ;
189
187
}
190
188
}
189
+
191
190
let path = Path :: new ( filename) ;
192
191
match OpenOptions :: new ( ) . write ( true ) . create ( create) . open ( path) {
193
192
Ok ( file) => file. set_len ( size) ,
194
193
Err ( e) if e. kind ( ) == ErrorKind :: NotFound && !create => Ok ( ( ) ) ,
195
194
Err ( e) => Err ( e) ,
196
195
}
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
+ } )
198
202
}
199
203
200
204
/// Truncate files to a size relative to a given file.
@@ -221,33 +225,49 @@ fn truncate_reference_and_size(
221
225
create : bool ,
222
226
) -> UResult < ( ) > {
223
227
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
+ }
225
237
Ok ( TruncateMode :: Absolute ( _) ) => {
226
238
return Err ( USimpleError :: new (
227
239
1 ,
228
- String :: from ( "you must specify a relative '-- size' with '--reference' ") ,
240
+ get_message ( "truncate-error- must- specify- relative- size") ,
229
241
) ) ;
230
242
}
231
243
Ok ( m) => m,
232
244
} ;
245
+
233
246
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
+ ) ) ;
235
251
}
252
+
236
253
let metadata = metadata ( rfilename) . map_err ( |e| match e. kind ( ) {
237
254
ErrorKind :: NotFound => USimpleError :: new (
238
255
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 ( ) ) ] ) ,
242
259
) ,
243
260
) ,
244
261
_ => e. map_err_context ( String :: new) ,
245
262
} ) ?;
263
+
246
264
let fsize = metadata. len ( ) ;
247
265
let tsize = mode. to_size ( fsize) ;
266
+
248
267
for filename in filenames {
249
268
file_truncate ( filename, create, tsize) ?;
250
269
}
270
+
251
271
Ok ( ( ) )
252
272
}
253
273
@@ -272,17 +292,20 @@ fn truncate_reference_file_only(
272
292
let metadata = metadata ( rfilename) . map_err ( |e| match e. kind ( ) {
273
293
ErrorKind :: NotFound => USimpleError :: new (
274
294
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 ( ) ) ] ) ,
278
298
) ,
279
299
) ,
280
300
_ => e. map_err_context ( String :: new) ,
281
301
} ) ?;
302
+
282
303
let tsize = metadata. len ( ) ;
304
+
283
305
for filename in filenames {
284
306
file_truncate ( filename, create, tsize) ?;
285
307
}
308
+
286
309
Ok ( ( ) )
287
310
}
288
311
@@ -304,21 +327,33 @@ fn truncate_reference_file_only(
304
327
///
305
328
/// If at least one file is a named pipe (also known as a fifo).
306
329
fn 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
+
309
340
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
+ ) ) ;
311
345
}
346
+
312
347
for filename in filenames {
313
348
let fsize = match metadata ( filename) {
314
349
Ok ( m) => {
315
350
#[ cfg( unix) ]
316
351
if m. file_type ( ) . is_fifo ( ) {
317
352
return Err ( USimpleError :: new (
318
353
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 ( ) ) ] ) ,
322
357
) ,
323
358
) ) ;
324
359
}
@@ -330,6 +365,7 @@ fn truncate_size_only(size_string: &str, filenames: &[String], create: bool) ->
330
365
// TODO: Fix duplicate call to stat
331
366
file_truncate ( filename, create, tsize) ?;
332
367
}
368
+
333
369
Ok ( ( ) )
334
370
}
335
371
@@ -341,6 +377,7 @@ fn truncate(
341
377
filenames : & [ String ] ,
342
378
) -> UResult < ( ) > {
343
379
let create = !no_create;
380
+
344
381
// There are four possibilities
345
382
// - reference file given and size given,
346
383
// - reference file given but no size given,
0 commit comments