@@ -10,7 +10,7 @@ use std::ffi::OsString;
10
10
use std:: fmt:: Display ;
11
11
use std:: fs:: { self , Metadata , OpenOptions , Permissions } ;
12
12
#[ cfg( unix) ]
13
- use std:: os:: unix:: fs:: { FileTypeExt , PermissionsExt } ;
13
+ use std:: os:: unix:: fs:: { FileTypeExt , MetadataExt , PermissionsExt } ;
14
14
#[ cfg( unix) ]
15
15
use std:: os:: unix:: net:: UnixListener ;
16
16
use std:: path:: { Path , PathBuf , StripPrefixError } ;
@@ -28,7 +28,7 @@ use platform::copy_on_write;
28
28
use uucore:: display:: Quotable ;
29
29
use uucore:: error:: { UError , UResult , UUsageError , set_exit_code} ;
30
30
#[ cfg( unix) ]
31
- use uucore:: fs:: make_fifo;
31
+ use uucore:: fs:: { make_fifo, make_char_device , make_block_device } ;
32
32
use uucore:: fs:: {
33
33
FileInformation , MissingHandling , ResolveMode , are_hardlinks_to_same_file, canonicalize,
34
34
get_filename, is_symlink_loop, normalize_path, path_ends_with_terminator,
@@ -2082,6 +2082,8 @@ fn handle_copy_mode(
2082
2082
source_in_command_line : bool ,
2083
2083
source_is_fifo : bool ,
2084
2084
source_is_socket : bool ,
2085
+ source_is_char_device : bool ,
2086
+ source_is_block_device : bool ,
2085
2087
#[ cfg( unix) ] source_is_stream : bool ,
2086
2088
) -> CopyResult < PerformedAction > {
2087
2089
let source_is_symlink = source_metadata. is_symlink ( ) ;
@@ -2122,6 +2124,8 @@ fn handle_copy_mode(
2122
2124
source_is_symlink,
2123
2125
source_is_fifo,
2124
2126
source_is_socket,
2127
+ source_is_char_device,
2128
+ source_is_block_device,
2125
2129
symlinked_files,
2126
2130
#[ cfg( unix) ]
2127
2131
source_is_stream,
@@ -2145,6 +2149,8 @@ fn handle_copy_mode(
2145
2149
source_is_symlink,
2146
2150
source_is_fifo,
2147
2151
source_is_socket,
2152
+ source_is_char_device,
2153
+ source_is_block_device,
2148
2154
symlinked_files,
2149
2155
#[ cfg( unix) ]
2150
2156
source_is_stream,
@@ -2181,6 +2187,8 @@ fn handle_copy_mode(
2181
2187
source_is_symlink,
2182
2188
source_is_fifo,
2183
2189
source_is_socket,
2190
+ source_is_char_device,
2191
+ source_is_block_device,
2184
2192
symlinked_files,
2185
2193
#[ cfg( unix) ]
2186
2194
source_is_stream,
@@ -2196,6 +2204,8 @@ fn handle_copy_mode(
2196
2204
source_is_symlink,
2197
2205
source_is_fifo,
2198
2206
source_is_socket,
2207
+ source_is_char_device,
2208
+ source_is_block_device,
2199
2209
symlinked_files,
2200
2210
#[ cfg( unix) ]
2201
2211
source_is_stream,
@@ -2424,10 +2434,18 @@ fn copy_file(
2424
2434
let source_is_fifo = source_metadata. file_type ( ) . is_fifo ( ) ;
2425
2435
#[ cfg( unix) ]
2426
2436
let source_is_socket = source_metadata. file_type ( ) . is_socket ( ) ;
2437
+ #[ cfg( unix) ]
2438
+ let source_is_char_device = source_metadata. file_type ( ) . is_char_device ( ) ;
2439
+ #[ cfg( unix) ]
2440
+ let source_is_block_device = source_metadata. file_type ( ) . is_block_device ( ) ;
2427
2441
#[ cfg( not( unix) ) ]
2428
2442
let source_is_fifo = false ;
2429
2443
#[ cfg( not( unix) ) ]
2430
2444
let source_is_socket = false ;
2445
+ #[ cfg( not( unix) ) ]
2446
+ let source_is_char_device = false ;
2447
+ #[ cfg( not( unix) ) ]
2448
+ let source_is_block_device = false ;
2431
2449
2432
2450
let source_is_stream = is_stream ( & source_metadata) ;
2433
2451
@@ -2441,6 +2459,8 @@ fn copy_file(
2441
2459
source_in_command_line,
2442
2460
source_is_fifo,
2443
2461
source_is_socket,
2462
+ source_is_char_device,
2463
+ source_is_block_device,
2444
2464
#[ cfg( unix) ]
2445
2465
source_is_stream,
2446
2466
) ?;
@@ -2568,6 +2588,8 @@ fn copy_helper(
2568
2588
source_is_symlink : bool ,
2569
2589
source_is_fifo : bool ,
2570
2590
source_is_socket : bool ,
2591
+ source_is_char_device : bool ,
2592
+ source_is_block_device : bool ,
2571
2593
symlinked_files : & mut HashSet < FileInformation > ,
2572
2594
#[ cfg( unix) ] source_is_stream : bool ,
2573
2595
) -> CopyResult < ( ) > {
@@ -2586,6 +2608,12 @@ fn copy_helper(
2586
2608
} else if source_is_fifo && options. recursive && !options. copy_contents {
2587
2609
#[ cfg( unix) ]
2588
2610
copy_fifo ( dest, options. overwrite , options. debug ) ?;
2611
+ } else if source_is_char_device && options. recursive && !options. copy_contents {
2612
+ #[ cfg( unix) ]
2613
+ copy_char_device ( source, dest, options. overwrite , options. debug ) ?;
2614
+ } else if source_is_block_device && options. recursive && !options. copy_contents {
2615
+ #[ cfg( unix) ]
2616
+ copy_block_device ( source, dest, options. overwrite , options. debug ) ?;
2589
2617
} else if source_is_symlink {
2590
2618
copy_link ( source, dest, symlinked_files, options) ?;
2591
2619
} else {
@@ -2620,6 +2648,40 @@ fn copy_fifo(dest: &Path, overwrite: OverwriteMode, debug: bool) -> CopyResult<(
2620
2648
. map_err ( |_| translate ! ( "cp-error-cannot-create-fifo" , "path" => dest. quote( ) ) . into ( ) )
2621
2649
}
2622
2650
2651
+ // "Copies" a character device by creating a new one with the same major/minor numbers.
2652
+ #[ cfg( unix) ]
2653
+ fn copy_char_device ( source : & Path , dest : & Path , overwrite : OverwriteMode , debug : bool ) -> CopyResult < ( ) > {
2654
+ if dest. exists ( ) {
2655
+ overwrite. verify ( dest, debug) ?;
2656
+ fs:: remove_file ( dest) ?;
2657
+ }
2658
+
2659
+ let source_metadata = fs:: metadata ( source) ?;
2660
+ let device_id = source_metadata. rdev ( ) ;
2661
+ let major = ( ( device_id >> 8 ) & 0xff ) as u32 ;
2662
+ let minor = ( device_id & 0xff ) as u32 ;
2663
+
2664
+ make_char_device ( dest, major, minor)
2665
+ . map_err ( |_| translate ! ( "cp-error-cannot-create-char-device" , "path" => dest. quote( ) ) . into ( ) )
2666
+ }
2667
+
2668
+ // "Copies" a block device by creating a new one with the same major/minor numbers.
2669
+ #[ cfg( unix) ]
2670
+ fn copy_block_device ( source : & Path , dest : & Path , overwrite : OverwriteMode , debug : bool ) -> CopyResult < ( ) > {
2671
+ if dest. exists ( ) {
2672
+ overwrite. verify ( dest, debug) ?;
2673
+ fs:: remove_file ( dest) ?;
2674
+ }
2675
+
2676
+ let source_metadata = fs:: metadata ( source) ?;
2677
+ let device_id = source_metadata. rdev ( ) ;
2678
+ let major = ( ( device_id >> 8 ) & 0xff ) as u32 ;
2679
+ let minor = ( device_id & 0xff ) as u32 ;
2680
+
2681
+ make_block_device ( dest, major, minor)
2682
+ . map_err ( |_| translate ! ( "cp-error-cannot-create-block-device" , "path" => dest. quote( ) ) . into ( ) )
2683
+ }
2684
+
2623
2685
#[ cfg( unix) ]
2624
2686
fn copy_socket ( dest : & Path , overwrite : OverwriteMode , debug : bool ) -> CopyResult < ( ) > {
2625
2687
if dest. exists ( ) {
0 commit comments