@@ -4,6 +4,8 @@ use serde::Serialize;
4
4
use std:: io:: Write ;
5
5
use std:: rc:: Rc ;
6
6
7
+ mod pe;
8
+
7
9
#[ derive( Debug , thiserror:: Error ) ]
8
10
#[ error( "unknown format({name})" ) ]
9
11
struct UnknownOutputFormat {
@@ -39,6 +41,8 @@ struct FindOption {
39
41
dir_only : bool ,
40
42
#[ clap( long, about = "output total size of directory(bytes)" ) ]
41
43
total_size : bool ,
44
+ #[ clap( long, about = "get PE file version if available" ) ]
45
+ get_version : bool ,
42
46
}
43
47
44
48
enum RecordWriter < T >
72
76
. as_ref ( )
73
77
. unwrap_or ( & String :: new ( ) )
74
78
. as_str ( ) ,
79
+ record. file_version . unwrap_or ( String :: new ( ) ) . as_str ( ) ,
80
+ record. product_version . unwrap_or ( String :: new ( ) ) . as_str ( ) ,
75
81
] ) ?;
76
82
}
77
83
Self :: NdJson ( v) => {
@@ -89,12 +95,15 @@ where
89
95
pub fn output_header ( & mut self ) -> Result < ( ) > {
90
96
match self {
91
97
Self :: Csv ( w) => {
98
+
92
99
w. write_record ( & [
93
100
"path" ,
94
101
"link_target" ,
95
102
"file_type" ,
96
103
"length" ,
97
104
"last_modified" ,
105
+ "file_version" ,
106
+ "product_version" ,
98
107
] ) ?;
99
108
}
100
109
Self :: NdJson ( _) => { } ,
@@ -111,6 +120,8 @@ struct FileRecord {
111
120
file_type : String ,
112
121
last_modified : Option < String > ,
113
122
link_target : Option < String > ,
123
+ file_version : Option < String > ,
124
+ product_version : Option < String > ,
114
125
}
115
126
116
127
enum OutputStream {
@@ -145,6 +156,7 @@ struct FindContext<'a> {
145
156
match_option : glob:: MatchOptions ,
146
157
dir_only : bool ,
147
158
output_total : bool ,
159
+ get_version : bool ,
148
160
}
149
161
150
162
fn create_record_writer (
@@ -199,6 +211,7 @@ impl<'a> FindContext<'a> {
199
211
match_option : match_option,
200
212
output_total : output_total,
201
213
dir_only : dir_only,
214
+ get_version : opts. get_version ,
202
215
} )
203
216
}
204
217
pub fn with_path ( mut self , new_path : & std:: path:: Path ) -> Self {
@@ -238,13 +251,18 @@ fn output_symlink_info<'a>(
238
251
None
239
252
} ;
240
253
if !ctx. dir_only {
254
+ let ( file_version, product_version) = if ctx. get_version {
255
+ pe:: read_version_from_dll ( path) . unwrap_or ( ( None , None ) )
256
+ } else { ( None , None ) } ;
241
257
write_record (
242
258
& mut ctx. output_stream ,
243
259
path. to_string_lossy ( ) . as_ref ( ) ,
244
260
Some ( link_target) ,
245
261
"link" ,
246
262
Some ( len) ,
247
263
modified,
264
+ file_version,
265
+ product_version
248
266
) ?;
249
267
}
250
268
Ok ( ( ctx, len) )
@@ -276,12 +294,17 @@ fn output_symlink_file_info<'a>(
276
294
None => ( None , None )
277
295
} ;
278
296
if !ctx. dir_only {
297
+ let ( file_version, product_version) = if ctx. get_version {
298
+ pe:: read_version_from_dll ( path) . unwrap_or ( ( None , None ) )
299
+ } else { ( None , None ) } ;
279
300
write_record ( ctx. output_stream ,
280
301
path. to_string_lossy ( ) . as_ref ( ) ,
281
302
Some ( link_target. to_string_lossy ( ) . as_ref ( ) ) ,
282
303
"file" ,
283
304
l,
284
- modified) ?;
305
+ modified,
306
+ file_version,
307
+ product_version) ?;
285
308
}
286
309
Ok ( ( ctx. with_path ( parent. as_path ( ) ) , l. unwrap_or ( 0 ) ) )
287
310
}
@@ -323,13 +346,16 @@ fn output_file_info<'a>(
323
346
None
324
347
} ;
325
348
if !ctx. dir_only {
349
+ let ( file_version, product_version) = pe:: read_version_from_dll ( path) . unwrap_or ( ( None , None ) ) ;
326
350
write_record (
327
351
& mut ctx. output_stream ,
328
352
path. to_string_lossy ( ) . as_ref ( ) ,
329
353
None ,
330
354
"file" ,
331
355
len,
332
356
modified,
357
+ file_version,
358
+ product_version
333
359
) ?;
334
360
}
335
361
Ok ( ( ctx. with_path ( parent. as_path ( ) ) , len. unwrap_or ( 0 ) ) )
@@ -361,6 +387,8 @@ fn write_record<T>(
361
387
file_type : & str ,
362
388
length : Option < u64 > ,
363
389
last_write : Option < std:: time:: SystemTime > ,
390
+ file_version : Option < String > ,
391
+ product_version : Option < String >
364
392
) -> Result < ( ) >
365
393
where
366
394
T : std:: io:: Write ,
@@ -378,6 +406,8 @@ where
378
406
file_type : file_type. to_owned ( ) ,
379
407
length : length,
380
408
last_modified : Some ( ststr) ,
409
+ file_version : file_version,
410
+ product_version : product_version,
381
411
} ) ?;
382
412
Ok ( ( ) )
383
413
}
@@ -457,6 +487,8 @@ fn retrieve_symlink<'a>(
457
487
"dir" ,
458
488
Some ( len) ,
459
489
modified,
490
+ None ,
491
+ None
460
492
) ?;
461
493
}
462
494
return Ok ( ( ctx_tmp, len) ) ;
@@ -583,6 +615,8 @@ fn enum_files_recursive<'a>(
583
615
"dir" ,
584
616
Some ( retval. 1 ) ,
585
617
last_write,
618
+ None ,
619
+ None
586
620
) ?;
587
621
}
588
622
current_total += retval. 1 ;
@@ -622,7 +656,7 @@ fn enum_files(pattern: &FindOption) -> Result<()> {
622
656
}
623
657
let ( root_ctx, root_size) = enum_files_recursive ( ctx, rootpath. as_path ( ) , 0 ) ?;
624
658
if root_ctx. output_total {
625
- write_record ( & mut record_writer, rootpath. as_path ( ) . to_string_lossy ( ) . as_ref ( ) , None , "dir" , Some ( root_size) , None ) ?;
659
+ write_record ( & mut record_writer, rootpath. as_path ( ) . to_string_lossy ( ) . as_ref ( ) , None , "dir" , Some ( root_size) , None , None , None ) ?;
626
660
}
627
661
}
628
662
Ok ( ( ) )
0 commit comments