Repository: thecoshman/http (language: rust)

Issue:
Build fails on musl host
When compiling https on `x86_64-unknown-linux-musl` build fails due a difference in the function signature of `ioctl`

```
$ rustc --version
rustc 1.43.1 (8d69840ab 2020-05-04)
```

```
$ cargo build
Compiling https v1.9.2 (/home/adrianisuru/http)
error[E0308]: mismatched types
  --> src/util/os/non_windows_non_macos.rs:39:47
   |
39 |             let ok = unsafe { ioctl(dev_file, BLKGETSIZE, &mut block_count as *mut c_ulong) } == 0;
   |                                               ^^^^^^^^^^ expected `i32`, found `u64`
   |
help: you can convert an `u64` to `i32` and panic if the converted value wouldn't fit
   |
39 |             let ok = unsafe { ioctl(dev_file, BLKGETSIZE.try_into().unwrap(), &mut block_count as *mut c_ulong) } == 0;
   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
  --> src/util/os/non_windows_non_macos.rs:39:47
   |
39 |             let ok = unsafe { ioctl(dev_file, BLKGETSIZE, &mut block_count as *mut c_ulong) } == 0;
   |                                               ^^^^^^^^^^ expected `i32`, found `u64`
   |
help: you can convert an `u64` to `i32` and panic if the converted value wouldn't fit
   |
39 |             let ok = unsafe { ioctl(dev_file, BLKGETSIZE.try_into().unwrap(), &mut block_count as *mut c_ulong) } == 0;
   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0308`.
error: could not compile `https`.

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: could not compile `https`.
```
On `glibc` systems the `ioctl` function signature is 
```c
extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;
```
but on `musl` systems the signature is
```c
int ioctl (int, int, ...);
```
so compiling [`src/util/os/non_windows_non_macos.rs`](https://github.com/thecoshman/http/blob/master/src/util/os/non_windows_non_macos.rs) fails because `BLKGETSIZE` is a `c_ulong` not a `c_int`


Discussion / hints:

Fix patch:
diff --git a/build.rs b/build.rs
index 973dc0c..c3cc83c 100644
--- a/build.rs
+++ b/build.rs
@@ -24,9 +24,15 @@ BLKGETSIZE
 #[cfg(not(any(target_os = "windows", target_os = "macos")))]
 static IOCTL_INCLUDE_SKELETON: &str = r#"
 /// Return `device size / 512` (`long *` arg)
-static BLKGETSIZE: c_ulong = {};
+static BLKGETSIZE: {type} = {expr} as {type};
 "#;
 
+#[cfg(all(not(any(target_os = "windows", target_os = "macos")), not(target_env = "musl")))]
+static IOCTL_REQUEST_TYPE: &str = "libc::c_ulong";
+
+#[cfg(all(not(any(target_os = "windows", target_os = "macos")), target_env = "musl"))]
+static IOCTL_REQUEST_TYPE: &str = "libc::c_int";
+
 
 fn main() {
     embed_resources();
@@ -49,8 +55,11 @@ fn get_ioctl_data() {
     File::create(&ioctl_source).unwrap().write_all(IOCTL_CHECK_SOURCE.as_bytes()).unwrap();
 
     let ioctl_preprocessed = String::from_utf8(cc::Build::new().file(ioctl_source).expand()).unwrap();
-    let blkgetsize_expr = ioctl_preprocessed.lines().next_back().unwrap().replace("U", " as c_ulong");
+    let blkgetsize_expr = ioctl_preprocessed.lines().next_back().unwrap().replace("U", "");
 
     let ioctl_include = ioctl_dir.join("ioctl.rs");
-    File::create(&ioctl_include).unwrap().write_all(IOCTL_INCLUDE_SKELETON.replace("{}", &blkgetsize_expr).as_bytes()).unwrap();
+    File::create(&ioctl_include)
+        .unwrap()
+        .write_all(IOCTL_INCLUDE_SKELETON.replace("{type}", IOCTL_REQUEST_TYPE).replace("{expr}", &blkgetsize_expr).as_bytes())
+        .unwrap();
 }


Test patch: