@@ -9,27 +9,59 @@ use std::mem::zeroed;
9
9
use std:: path:: { Path , PathBuf } ;
10
10
use std:: ptr;
11
11
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
12
- use std:: time:: SystemTime ;
13
12
14
13
use libbzip2_rs_sys:: {
15
14
BZ2_bzRead , BZ2_bzReadClose , BZ2_bzReadGetUnused , BZ2_bzReadOpen , BZ2_bzWrite ,
16
15
BZ2_bzWriteClose64 , BZ2_bzWriteOpen , BZ2_bzlibVersion , BZFILE ,
17
16
} ;
18
17
19
18
use libc:: {
20
- _exit, close, exit, fclose, fdopen, ferror, fflush, fgetc, fileno, fopen, fread, fwrite, open,
21
- perror, remove, rewind, signal, stat, strlen, ungetc, utimbuf, write, FILE , O_CREAT , O_EXCL ,
22
- O_WRONLY , SIGBUS , SIGHUP , SIGINT , SIGSEGV , SIGTERM , S_IRUSR , S_IWUSR ,
19
+ _exit, exit, fclose, ferror, fflush, fgetc, fileno, fopen, fread, fwrite, perror, remove,
20
+ rewind, signal, stat, strlen, ungetc, write, FILE , SIGINT , SIGSEGV , SIGTERM ,
23
21
} ;
24
22
25
23
// FIXME remove this
24
+ #[ cfg( not( target_os = "windows" ) ) ]
26
25
extern "C" {
27
26
#[ cfg_attr( target_os = "macos" , link_name = "__stdinp" ) ]
28
27
static mut stdin: * mut FILE ;
29
28
#[ cfg_attr( target_os = "macos" , link_name = "__stdoutp" ) ]
30
29
static mut stdout: * mut FILE ;
31
30
}
32
31
32
+ #[ cfg( all( target_os = "windows" , target_env = "gnu" ) ) ]
33
+ extern "C" {
34
+ fn __acrt_iob_func ( idx : libc:: c_uint ) -> * mut FILE ;
35
+ }
36
+
37
+ #[ cfg( not( target_os = "windows" ) ) ]
38
+ macro_rules! STDIN {
39
+ ( ) => {
40
+ stdin
41
+ } ;
42
+ }
43
+
44
+ #[ cfg( all( target_os = "windows" , target_env = "gnu" ) ) ]
45
+ macro_rules! STDIN {
46
+ ( ) => {
47
+ __acrt_iob_func( 0 )
48
+ } ;
49
+ }
50
+
51
+ #[ cfg( not( target_os = "windows" ) ) ]
52
+ macro_rules! STDOUT {
53
+ ( ) => {
54
+ stdout
55
+ } ;
56
+ }
57
+
58
+ #[ cfg( all( target_os = "windows" , target_env = "gnu" ) ) ]
59
+ macro_rules! STDOUT {
60
+ ( ) => {
61
+ __acrt_iob_func( 1 )
62
+ } ;
63
+ }
64
+
33
65
type Bool = libc:: c_uchar ;
34
66
35
67
type IntNative = libc:: c_int ;
@@ -126,7 +158,8 @@ unsafe fn compressStream(stream: *mut FILE, zStream: *mut FILE, metadata: Option
126
158
let mut bzerr_dummy: i32 = 0 ;
127
159
let mut ret: i32 ;
128
160
129
- // TODO set files to binary mode?
161
+ set_binary_mode ( stream) ;
162
+ set_binary_mode ( zStream) ;
130
163
131
164
if ferror ( stream) != 0 {
132
165
// diverges
@@ -291,7 +324,8 @@ unsafe fn uncompressStream(
291
324
292
325
let mut state = State :: Standard ;
293
326
294
- // TODO: set the file into binary mode?
327
+ set_binary_mode ( stream) ;
328
+ set_binary_mode ( zStream) ;
295
329
296
330
if ferror ( stream) != 0 || ferror ( zStream) != 0 {
297
331
// diverges
@@ -395,7 +429,7 @@ unsafe fn uncompressStream(
395
429
ioError ( )
396
430
}
397
431
398
- if stream != stdout {
432
+ if stream != STDOUT ! ( ) {
399
433
ret = fclose ( stream) ;
400
434
outputHandleJustInCase = core:: ptr:: null_mut ( ) ;
401
435
if ret == libc:: EOF {
@@ -458,10 +492,10 @@ unsafe fn uncompressStream(
458
492
libbzip2_rs_sys:: BZ_MEM_ERROR => outOfMemory ( ) ,
459
493
libbzip2_rs_sys:: BZ_UNEXPECTED_EOF => compressedStreamEOF ( ) ,
460
494
libbzip2_rs_sys:: BZ_DATA_ERROR_MAGIC => {
461
- if zStream != stdin {
495
+ if zStream != STDIN ! ( ) {
462
496
fclose ( zStream) ;
463
497
}
464
- if stream != stdout {
498
+ if stream != STDOUT ! ( ) {
465
499
fclose ( stream) ;
466
500
}
467
501
if streamNo == 1 {
@@ -587,7 +621,7 @@ unsafe fn testStream(zStream: *mut FILE) -> bool {
587
621
false
588
622
}
589
623
libbzip2_rs_sys:: BZ_DATA_ERROR_MAGIC => {
590
- if zStream != stdin {
624
+ if zStream != STDIN ! ( ) {
591
625
fclose ( zStream) ;
592
626
}
593
627
if streamNo == 1 {
@@ -903,44 +937,65 @@ unsafe fn copy_filename(to: *mut c_char, from: &str) {
903
937
}
904
938
905
939
fn fopen_output_safely_rust ( name : impl AsRef < Path > ) -> * mut FILE {
906
- use std:: os:: fd:: IntoRawFd ;
907
- use std:: os:: unix:: fs:: OpenOptionsExt ;
940
+ #[ cfg( unix) ]
941
+ {
942
+ use std:: os:: fd:: IntoRawFd ;
943
+ use std:: os:: unix:: fs:: OpenOptionsExt ;
908
944
909
- let mut opts = std:: fs:: File :: options ( ) ;
945
+ let mut opts = std:: fs:: File :: options ( ) ;
910
946
911
- opts. write ( true ) . create_new ( true ) ;
947
+ opts. write ( true ) . create_new ( true ) ;
912
948
913
- #[ allow( clippy:: unnecessary_cast) ]
914
- opts. mode ( ( libc:: S_IWUSR | libc:: S_IRUSR ) as u32 ) ;
949
+ #[ allow( clippy:: unnecessary_cast) ]
950
+ opts. mode ( ( libc:: S_IWUSR | libc:: S_IRUSR ) as u32 ) ;
915
951
916
- let Ok ( file) = opts. open ( name) else {
917
- return std:: ptr:: null_mut :: < FILE > ( ) ;
918
- } ;
952
+ let Ok ( file) = opts. open ( name) else {
953
+ return std:: ptr:: null_mut :: < FILE > ( ) ;
954
+ } ;
919
955
920
- let fd = file. into_raw_fd ( ) ;
921
- let mode = b"wb\0 " . as_ptr ( ) . cast :: < c_char > ( ) ;
922
- let fp = unsafe { fdopen ( fd, mode) } ;
923
- if fp. is_null ( ) {
924
- unsafe { close ( fd) } ;
956
+ let fd = file. into_raw_fd ( ) ;
957
+ let mode = b"wb\0 " . as_ptr ( ) . cast :: < c_char > ( ) ;
958
+ let fp = unsafe { libc:: fdopen ( fd, mode) } ;
959
+ if fp. is_null ( ) {
960
+ unsafe { libc:: close ( fd) } ;
961
+ }
962
+ fp
925
963
}
926
964
927
- fp
965
+ #[ cfg( not( unix) ) ]
966
+ unsafe {
967
+ use std:: ffi:: CString ;
968
+
969
+ // The CString really only needs to live for the duration of the fopen
970
+ #[ allow( temporary_cstring_as_ptr) ]
971
+ libc:: fopen (
972
+ CString :: new ( name. as_ref ( ) . to_str ( ) . unwrap ( ) )
973
+ . unwrap ( )
974
+ . as_ptr ( ) ,
975
+ b"wb\0 " . as_ptr ( ) . cast :: < c_char > ( ) ,
976
+ )
977
+ }
928
978
}
929
979
930
980
unsafe fn fopen_output_safely ( name : * mut c_char , mode : * const libc:: c_char ) -> * mut FILE {
931
- let fh = open (
932
- name,
933
- O_WRONLY | O_CREAT | O_EXCL ,
934
- S_IWUSR as libc:: c_uint | S_IRUSR as libc:: c_uint ,
935
- ) ;
936
- if fh == -1 as libc:: c_int {
937
- return std:: ptr:: null_mut :: < FILE > ( ) ;
938
- }
939
- let fp = fdopen ( fh, mode) ;
940
- if fp. is_null ( ) {
941
- close ( fh) ;
981
+ #[ cfg( unix) ]
982
+ {
983
+ let fh = libc:: open (
984
+ name,
985
+ libc:: O_WRONLY | libc:: O_CREAT | libc:: O_EXCL ,
986
+ libc:: S_IWUSR as libc:: c_uint | libc:: S_IRUSR as libc:: c_uint ,
987
+ ) ;
988
+ if fh == -1 as libc:: c_int {
989
+ return std:: ptr:: null_mut :: < FILE > ( ) ;
990
+ }
991
+ let fp = libc:: fdopen ( fh, mode) ;
992
+ if fp. is_null ( ) {
993
+ libc:: close ( fh) ;
994
+ }
995
+ fp
942
996
}
943
- fp
997
+ #[ cfg( not( unix) ) ]
998
+ libc:: fopen ( name, mode)
944
999
}
945
1000
946
1001
fn not_a_standard_file ( path : & Path ) -> bool {
@@ -963,21 +1018,23 @@ fn count_hardlinks(path: &Path) -> u64 {
963
1018
}
964
1019
965
1020
#[ cfg( not( unix) ) ]
966
- unsafe fn count_hardlinks ( path : & Path ) -> u64 {
1021
+ unsafe fn count_hardlinks ( _path : & Path ) -> u64 {
967
1022
0 // FIXME
968
1023
}
969
1024
970
1025
fn apply_saved_time_info_to_output_file ( _dst_name : & CStr , _metadata : Metadata ) {
971
1026
#[ cfg( unix) ]
972
1027
{
1028
+ use std:: time:: SystemTime ;
1029
+
973
1030
let convert = |x : SystemTime | {
974
1031
x. duration_since ( SystemTime :: UNIX_EPOCH ) . unwrap ( ) . as_secs ( ) as libc:: time_t
975
1032
} ;
976
1033
977
1034
let actime = convert ( _metadata. accessed ( ) . unwrap_or ( SystemTime :: UNIX_EPOCH ) ) ;
978
1035
let modtime = convert ( _metadata. modified ( ) . unwrap_or ( SystemTime :: UNIX_EPOCH ) ) ;
979
1036
980
- let buf = utimbuf { actime, modtime } ;
1037
+ let buf = libc :: utimbuf { actime, modtime } ;
981
1038
982
1039
match unsafe { libc:: utime ( _dst_name. as_ptr ( ) , & buf) } {
983
1040
0 => { }
@@ -986,24 +1043,24 @@ fn apply_saved_time_info_to_output_file(_dst_name: &CStr, _metadata: Metadata) {
986
1043
}
987
1044
}
988
1045
989
- unsafe fn set_permissions ( handle : * mut FILE , metadata : & Metadata ) {
1046
+ unsafe fn set_permissions ( _handle : * mut FILE , _metadata : & Metadata ) {
990
1047
#[ cfg( unix) ]
991
1048
{
992
1049
use std:: os:: unix:: fs:: MetadataExt ;
993
1050
994
- let fd = fileno ( handle ) ;
1051
+ let fd = fileno ( _handle ) ;
995
1052
if fd < 0 {
996
1053
// diverges
997
1054
ioError ( )
998
1055
}
999
1056
1000
- let retVal = libc:: fchmod ( fd, metadata . mode ( ) as libc:: mode_t ) ;
1057
+ let retVal = libc:: fchmod ( fd, _metadata . mode ( ) as libc:: mode_t ) ;
1001
1058
if retVal != 0 as libc:: c_int {
1002
1059
ioError ( ) ;
1003
1060
}
1004
1061
1005
1062
// chown() will in many cases return with EPERM, which can be safely ignored.
1006
- libc:: fchown ( fd, metadata . uid ( ) , metadata . gid ( ) ) ;
1063
+ libc:: fchown ( fd, _metadata . uid ( ) , _metadata . gid ( ) ) ;
1007
1064
}
1008
1065
}
1009
1066
@@ -1031,6 +1088,24 @@ const BZ_N_SUFFIX_PAIRS: usize = 4;
1031
1088
const Z_SUFFIX : [ & str ; BZ_N_SUFFIX_PAIRS ] = [ ".bz2" , ".bz" , ".tbz2" , ".tbz" ] ;
1032
1089
const UNZ_SUFFIX : [ & str ; BZ_N_SUFFIX_PAIRS ] = [ "" , "" , ".tar" , ".tar" ] ;
1033
1090
1091
+ #[ cfg( windows) ]
1092
+ /// Prevent Windows from mangling the read data.
1093
+ unsafe fn set_binary_mode ( file : * mut FILE ) {
1094
+ use std:: ffi:: c_int;
1095
+
1096
+ extern "C" {
1097
+ fn _setmode ( fd : c_int , mode : c_int ) -> c_int ;
1098
+ }
1099
+
1100
+ if _setmode ( fileno ( file) , libc:: O_BINARY ) == -1 {
1101
+ ioError ( ) ;
1102
+ }
1103
+ }
1104
+
1105
+ #[ cfg( not( windows) ) ]
1106
+ /// Prevent Windows from mangling the read data.
1107
+ unsafe fn set_binary_mode ( _file : * mut FILE ) { }
1108
+
1034
1109
unsafe fn compress ( name : Option < & str > ) {
1035
1110
let in_name;
1036
1111
let out_name;
@@ -1165,8 +1240,8 @@ unsafe fn compress(name: Option<&str>) {
1165
1240
1166
1241
match srcMode {
1167
1242
SourceMode :: I2O => {
1168
- inStr = stdin ;
1169
- outStr = stdout ;
1243
+ inStr = STDIN ! ( ) ;
1244
+ outStr = STDOUT ! ( ) ;
1170
1245
if std:: io:: stdout ( ) . is_terminal ( ) {
1171
1246
eprintln ! (
1172
1247
"{}: I won't write compressed data to a terminal." ,
@@ -1186,7 +1261,7 @@ unsafe fn compress(name: Option<&str>) {
1186
1261
inName. as_mut_ptr ( ) ,
1187
1262
b"rb\0 " as * const u8 as * const libc:: c_char ,
1188
1263
) ;
1189
- outStr = stdout ;
1264
+ outStr = STDOUT ! ( ) ;
1190
1265
if std:: io:: stdout ( ) . is_terminal ( ) {
1191
1266
eprintln ! (
1192
1267
"{}: I won't write compressed data to a terminal." ,
@@ -1416,8 +1491,8 @@ unsafe fn uncompress(name: Option<&str>) {
1416
1491
1417
1492
match srcMode {
1418
1493
SourceMode :: I2O => {
1419
- inStr = stdin ;
1420
- outStr = stdout ;
1494
+ inStr = STDIN ! ( ) ;
1495
+ outStr = STDOUT ! ( ) ;
1421
1496
if std:: io:: stdin ( ) . is_terminal ( ) {
1422
1497
eprint ! (
1423
1498
concat!(
@@ -1435,7 +1510,7 @@ unsafe fn uncompress(name: Option<&str>) {
1435
1510
inName. as_mut_ptr ( ) ,
1436
1511
b"rb\0 " as * const u8 as * const libc:: c_char ,
1437
1512
) ;
1438
- outStr = stdout ;
1513
+ outStr = STDOUT ! ( ) ;
1439
1514
if inStr. is_null ( ) {
1440
1515
eprintln ! (
1441
1516
"{}: Can't open input file {}: {}." ,
@@ -1616,7 +1691,7 @@ unsafe fn testf(name: Option<&str>) {
1616
1691
setExit ( 1 ) ;
1617
1692
return ;
1618
1693
}
1619
- inStr = stdin ;
1694
+ inStr = STDIN ! ( ) ;
1620
1695
}
1621
1696
SourceMode :: F2O | SourceMode :: F2F => {
1622
1697
inStr = fopen (
@@ -1751,8 +1826,9 @@ unsafe fn main_0(program_path: &Path) -> IntNative {
1751
1826
SIGSEGV ,
1752
1827
mySIGSEGVorSIGBUScatcher as unsafe extern "C" fn ( libc:: c_int ) as usize ,
1753
1828
) ;
1829
+ #[ cfg( not( target_os = "windows" ) ) ]
1754
1830
signal (
1755
- SIGBUS ,
1831
+ libc :: SIGBUS ,
1756
1832
mySIGSEGVorSIGBUScatcher as unsafe extern "C" fn ( libc:: c_int ) as usize ,
1757
1833
) ;
1758
1834
@@ -1922,8 +1998,9 @@ unsafe fn main_0(program_path: &Path) -> IntNative {
1922
1998
SIGTERM ,
1923
1999
mySignalCatcher as unsafe extern "C" fn ( IntNative ) as usize ,
1924
2000
) ;
2001
+ #[ cfg( not( target_os = "windows" ) ) ]
1925
2002
signal (
1926
- SIGHUP ,
2003
+ libc :: SIGHUP ,
1927
2004
mySignalCatcher as unsafe extern "C" fn ( IntNative ) as usize ,
1928
2005
) ;
1929
2006
}
0 commit comments