diff --git a/libc-test/build.rs b/libc-test/build.rs index 0c1b976c8e11b..aba2a3056852c 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -1931,5 +1931,9 @@ fn test_wasi(target: &str) { // import the same thing but have different function pointers cfg.skip_fn_ptrcheck(|f| f.starts_with("__wasi")); + // d_name is declared as a flexible array in WASI libc, so it + // doesn't support sizeof. + cfg.skip_field(|s, field| s == "dirent" && field == "d_name"); + cfg.generate("../src/lib.rs", "main.rs"); } diff --git a/src/wasi.rs b/src/wasi.rs index ee368adf376be..42cb33f4924ae 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -141,12 +141,6 @@ s! { fds_bits: [c_ulong; FD_SETSIZE / ULONG_SIZE], } - pub struct dirent { - pub d_ino: ino_t, - pub d_type: c_uchar, - pub d_name: [c_char; 1024], - } - pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, @@ -303,6 +297,20 @@ s_no_extra_traits! { } +// Declare dirent outside of s! so that it doesn't implement Copy, Eq, Hash, +// etc., since it contains a flexible array member with a dynamic size. +#[repr(C)] +#[allow(missing_copy_implementations)] +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub struct dirent { + pub d_ino: ino_t, + pub d_type: c_uchar, + /// d_name is declared in WASI libc as a flexible array member, which + /// can't be directly expressed in Rust. As an imperfect workaround, + /// declare it as a zero-length array instead. + pub d_name: [c_char; 0], +} + // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] {