@@ -25,7 +25,6 @@ use progress::ProgUpdateType;
2525use progress:: { ProgUpdate , ReadStat , StatusLevel , WriteStat , gen_prog_updater} ;
2626#[ cfg( target_os = "linux" ) ]
2727use progress:: { check_and_reset_sigusr1, install_sigusr1_handler} ;
28- use uucore:: io:: OwnedFileDescriptorOrHandle ;
2928use uucore:: translate;
3029
3130use std:: cmp;
@@ -625,7 +624,7 @@ enum Density {
625624/// Data destinations.
626625enum Dest {
627626 /// Output to stdout.
628- Stdout ( File ) ,
627+ StdoutRaw ( StdoutRaw ) ,
629628
630629 /// Output to a file.
631630 ///
@@ -645,7 +644,7 @@ enum Dest {
645644impl Dest {
646645 fn fsync ( & mut self ) -> io:: Result < ( ) > {
647646 match self {
648- Self :: Stdout ( stdout) => stdout. flush ( ) ,
647+ Self :: StdoutRaw ( stdout) => stdout. flush ( ) ,
649648 Self :: File ( f, _) => {
650649 f. flush ( ) ?;
651650 f. sync_all ( )
@@ -662,7 +661,7 @@ impl Dest {
662661
663662 fn fdatasync ( & mut self ) -> io:: Result < ( ) > {
664663 match self {
665- Self :: Stdout ( stdout) => stdout. flush ( ) ,
664+ Self :: StdoutRaw ( stdout) => stdout. flush ( ) ,
666665 Self :: File ( f, _) => {
667666 f. flush ( ) ?;
668667 f. sync_data ( )
@@ -680,7 +679,7 @@ impl Dest {
680679 #[ cfg_attr( not( unix) , allow( unused_variables) ) ]
681680 fn seek ( & mut self , n : u64 , obs : usize ) -> io:: Result < u64 > {
682681 match self {
683- Self :: Stdout ( stdout) => io:: copy ( & mut io:: repeat ( 0 ) . take ( n) , stdout) ,
682+ Self :: StdoutRaw ( stdout) => io:: copy ( & mut io:: repeat ( 0 ) . take ( n) , & mut * * stdout) ,
684683 Self :: File ( f, _) => {
685684 #[ cfg( unix) ]
686685 if let Ok ( Some ( len) ) = try_get_len_of_block_device ( f)
@@ -790,6 +789,38 @@ fn handle_o_direct_write(
790789 Err ( original_error)
791790}
792791
792+ struct StdoutRaw ( core:: mem:: ManuallyDrop < File > ) ;
793+
794+ impl StdoutRaw {
795+ #[ cfg( not( windows) ) ]
796+ fn new ( ) -> Self {
797+ let fd = io:: stdout ( ) . as_raw_fd ( ) ;
798+ let f = unsafe { File :: from_raw_fd ( fd) } ;
799+ Self ( core:: mem:: ManuallyDrop :: new ( f) )
800+ }
801+
802+ #[ cfg( windows) ]
803+ fn new ( ) -> Self {
804+ let handle = std:: os:: windows:: io:: AsRawHandle :: as_raw_handle ( & io:: stdout ( ) ) ;
805+ let f = unsafe { std:: os:: windows:: io:: FromRawHandle :: from_raw_handle ( handle) } ;
806+ Self ( core:: mem:: ManuallyDrop :: new ( f) )
807+ }
808+ }
809+
810+ impl core:: ops:: Deref for StdoutRaw {
811+ type Target = File ;
812+
813+ fn deref ( & self ) -> & Self :: Target {
814+ & self . 0
815+ }
816+ }
817+
818+ impl core:: ops:: DerefMut for StdoutRaw {
819+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
820+ & mut self . 0
821+ }
822+ }
823+
793824impl Write for Dest {
794825 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
795826 match self {
@@ -816,7 +847,7 @@ impl Write for Dest {
816847 Err ( e) => Err ( e) ,
817848 }
818849 }
819- Self :: Stdout ( stdout) => stdout. write ( buf) ,
850+ Self :: StdoutRaw ( stdout) => stdout. write ( buf) ,
820851 #[ cfg( unix) ]
821852 Self :: Fifo ( f) => f. write ( buf) ,
822853 #[ cfg( unix) ]
@@ -826,7 +857,7 @@ impl Write for Dest {
826857
827858 fn flush ( & mut self ) -> io:: Result < ( ) > {
828859 match self {
829- Self :: Stdout ( stdout) => stdout. flush ( ) ,
860+ Self :: StdoutRaw ( stdout) => stdout. flush ( ) ,
830861 Self :: File ( f, _) => f. flush ( ) ,
831862 #[ cfg( unix) ]
832863 Self :: Fifo ( f) => f. flush ( ) ,
@@ -853,8 +884,8 @@ struct Output<'a> {
853884impl < ' a > Output < ' a > {
854885 /// Instantiate this struct with stdout as a destination.
855886 fn new_stdout ( settings : & ' a Settings ) -> UResult < Self > {
856- let fx = OwnedFileDescriptorOrHandle :: from ( io :: stdout ( ) ) ? ;
857- let mut dst = Dest :: Stdout ( fx . into_file ( ) ) ;
887+ let stdout = StdoutRaw :: new ( ) ;
888+ let mut dst = Dest :: StdoutRaw ( stdout ) ;
858889 dst. seek ( settings. seek , settings. obs )
859890 . map_err_context ( || translate ! ( "dd-error-write-error" ) ) ?;
860891 Ok ( Self { dst, settings } )
@@ -914,16 +945,17 @@ impl<'a> Output<'a> {
914945 /// already opened by the system (stdout) and has a state
915946 /// (current position) that shall be used.
916947 fn new_file_from_stdout ( settings : & ' a Settings ) -> UResult < Self > {
917- let fx = OwnedFileDescriptorOrHandle :: from ( io :: stdout ( ) ) ? ;
948+ let stdout = StdoutRaw :: new ( ) ;
918949 #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
919950 if let Some ( libc_flags) = make_linux_oflags ( & settings. oflags ) {
920951 nix:: fcntl:: fcntl (
921- fx . as_raw ( ) . as_fd ( ) ,
952+ stdout . as_fd ( ) ,
922953 FcntlArg :: F_SETFL ( OFlag :: from_bits_retain ( libc_flags) ) ,
923954 ) ?;
924955 }
925956
926- Self :: prepare_file ( fx. into_file ( ) , settings)
957+ // TODO: avoid cloning the underlying file descriptor here
958+ Self :: prepare_file ( stdout. try_clone ( ) ?, settings)
927959 }
928960
929961 /// Instantiate this struct with the given named pipe as a destination.
0 commit comments