diff --git a/libc-test/build.rs b/libc-test/build.rs
index 29e43f6d1431bfa3b04ae31be6ca5a30f1b2b8be..a4228922dfbda59ed7e0d8529d7a7fe041bc8c25 100644
--- a/libc-test/build.rs
+++ b/libc-test/build.rs
@@ -343,7 +343,7 @@ fn main() {
         }
     }
 
-    cfg.type_name(move |ty, is_struct| {
+    cfg.type_name(move |ty, is_struct, is_union| {
         match ty {
             // Just pass all these through, no need for a "struct" prefix
             "FILE" |
@@ -360,6 +360,10 @@ fn main() {
             // OSX calls this something else
             "sighandler_t" if bsdlike => "sig_t".to_string(),
 
+            t if is_union => {
+                format!("union {}", t)
+            }
+
             t if t.ends_with("_t") => t.to_string(),
 
             // Windows uppercase structs don't have `struct` in front, there's a
@@ -822,9 +826,10 @@ fn main() {
         cfg.skip_struct(|s| {
             s != "termios2"
         });
-        cfg.type_name(move |ty, is_struct| {
+        cfg.type_name(move |ty, is_struct, is_union| {
             match ty {
                 t if is_struct => format!("struct {}", t),
+                t if is_union => format!("union {}", t),
                 t => t.to_string(),
             }
         });
diff --git a/src/macros.rs b/src/macros.rs
index 0e13bfcf46611bc7c8c3684f188fdb2bc7ee8186..2abab5002fcf7b0f70f035b27ce5882083326b02 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -35,11 +35,11 @@ macro_rules! __cfg_if_apply {
 }
 
 macro_rules! s {
-    ($($(#[$attr:meta])* pub struct $i:ident { $($field:tt)* })*) => ($(
+    ($($(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($(
         __item! {
             #[repr(C)]
             $(#[$attr])*
-            pub struct $i { $($field)* }
+            pub $t $i { $($field)* }
         }
         impl ::dox::Copy for $i {}
         impl ::dox::Clone for $i {
diff --git a/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/src/unix/bsd/freebsdlike/dragonfly/mod.rs
index f399f27ccb09b91343fe335e4593251eb653f557..9e1082e53bf8152cdf254e45dc55e5fc7effd947 100644
--- a/src/unix/bsd/freebsdlike/dragonfly/mod.rs
+++ b/src/unix/bsd/freebsdlike/dragonfly/mod.rs
@@ -115,6 +115,27 @@ s! {
         pub f_uid_uuid: ::uuid_t,
     }
 
+    pub struct statfs {
+        pub f_bsize: ::c_long,
+        pub f_iosize: ::c_long,
+        pub f_blocks: ::c_long,
+        pub f_bfree: ::c_long,
+        pub f_bavail: ::c_long,
+        pub f_files: ::c_long,
+        pub f_ffree: ::c_long,
+        pub f_fsid: ::fsid_t,
+        pub f_owner: ::uid_t,
+        pub f_type: ::int32_t,
+        pub f_flags: ::int32_t,
+        pub f_syncwrites: ::c_long,
+        pub f_asyncwrites: ::c_long,
+        pub f_fstypename: [::c_char; 16],
+        pub f_mntonname: [::c_char; 90],
+        pub f_syncreads: ::c_long,
+        pub f_asyncreads: ::c_long,
+        pub f_mntfromname: [::c_char; 90],
+    }
+
     pub struct stat {
         pub st_ino: ::ino_t,
         pub st_nlink: ::nlink_t,
@@ -760,4 +781,7 @@ extern {
 
     pub fn lwp_rtprio(function: ::c_int, pid: ::pid_t, lwpid: lwpid_t,
                       rtp: *mut super::rtprio) -> ::c_int;
+
+    pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int;
+    pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int;
 }
diff --git a/src/unix/bsd/freebsdlike/freebsd/mod.rs b/src/unix/bsd/freebsdlike/freebsd/mod.rs
index def81dfe2e4c454601eb9ff336a40496f5208828..a64dbc468f0d3788ef4b889621eb89d629c6fd1a 100644
--- a/src/unix/bsd/freebsdlike/freebsd/mod.rs
+++ b/src/unix/bsd/freebsdlike/freebsd/mod.rs
@@ -99,6 +99,31 @@ s! {
         pub f_namemax: ::c_ulong,
     }
 
+    pub struct statfs {
+        pub f_version: ::uint32_t,
+        pub f_type: ::uint32_t,
+        pub f_flags: ::uint64_t,
+        pub f_bsize: ::uint64_t,
+        pub f_iosize: ::uint64_t,
+        pub f_blocks: ::uint64_t,
+        pub f_bfree: ::uint64_t,
+        pub f_bavail: ::int64_t,
+        pub f_files: ::uint64_t,
+        pub f_ffree: ::int64_t,
+        pub f_syncwrites: ::uint64_t,
+        pub f_asyncwrites: ::uint64_t,
+        pub f_syncreads: ::uint64_t,
+        pub f_asyncreads: ::uint64_t,
+        f_spare: [::uint64_t; 10],
+        pub f_namemax: ::uint32_t,
+        pub f_owner: ::uid_t,
+        pub f_fsid: ::fsid_t,
+        f_charspare: [::c_char; 80],
+        pub f_fstypename: [::c_char; 16],
+        pub f_mntfromname: [::c_char; 88],
+        pub f_mntonname: [::c_char; 88],
+    }
+
     // internal structure has changed over time
     pub struct _sem {
         data: [u32; 4],
@@ -994,6 +1019,9 @@ extern {
         fd: ::c_int,
         newfd: ::c_int,
     ) -> ::c_int;
+
+    pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int;
+    pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int;
 }
 
 cfg_if! {
diff --git a/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs b/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs
index cca8a47ae098f86d8e32401e1fde607d2695f545..e2d1a5ad6183358c3ca8918dad8c51b76b421fcb 100644
--- a/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs
+++ b/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs
@@ -25,8 +25,207 @@ s! {
         pub int_p_sign_posn: ::c_char,
         pub int_n_sign_posn: ::c_char,
     }
+
+    pub struct statfs {
+        pub f_flags: ::uint32_t,
+        pub f_bsize: ::uint32_t,
+        pub f_iosize: ::uint32_t,
+        pub f_blocks: ::uint64_t,
+        pub f_bfree: ::uint64_t,
+        pub f_bavail: ::int64_t,
+        pub f_files: ::uint64_t,
+        pub f_ffree: ::uint64_t,
+        pub f_favail: ::int64_t,
+        pub f_syncwrites: ::uint64_t,
+        pub f_syncreads: ::uint64_t,
+        pub f_asyncwrites: ::uint64_t,
+        pub f_asyncreads: ::uint64_t,
+        pub f_fsid: ::fsid_t,
+        pub f_namemax: ::uint32_t,
+        pub f_owner: ::uid_t,
+        pub f_ctime: ::uint64_t,
+        pub f_fstypename: [::c_char; 16],
+        pub f_mntonname: [::c_char; 90],
+        pub f_mntfromname: [::c_char; 90],
+        pub f_mntfromspec: [::c_char; 90],
+        pub mount_info: mount_info,
+    }
+
+    pub union mount_info {
+        pub ufs_args: ufs_args,
+        pub mfs_args: mfs_args,
+        pub nfs_args: nfs_args,
+        pub iso_args: iso_args,
+        pub msdosfs_args: msdosfs_args,
+        pub ntfs_args: ntfs_args,
+        pub tmpfs_args: tmpfs_args,
+        align: [::c_char; 160],
+    }
+
+    pub struct ufs_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+    }
+
+    pub struct mfs_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+        // https://github.com/openbsd/src/blob/master/sys/sys/types.h#L134
+        pub base: *mut ::c_char,
+        pub size: ::c_ulong,
+    }
+
+    pub struct iso_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+        pub flags: ::c_int,
+        pub sess: ::c_int,
+    }
+
+    pub struct nfs_args {
+        pub version: ::c_int,
+        pub addr: *mut ::sockaddr,
+        pub addrlen: ::c_int,
+        pub sotype: ::c_int,
+        pub proto: ::c_int,
+        pub fh: *mut ::c_uchar,
+        pub fhsize: ::c_int,
+        pub flags: ::c_int,
+        pub wsize: ::c_int,
+        pub rsize: ::c_int,
+        pub readdirsize: ::c_int,
+        pub timeo: ::c_int,
+        pub retrans: ::c_int,
+        pub maxgrouplist: ::c_int,
+        pub readahead: ::c_int,
+        pub leaseterm: ::c_int,
+        pub deadthresh: ::c_int,
+        pub hostname: *mut ::c_char,
+        pub acregmin: ::c_int,
+        pub acregmax: ::c_int,
+        pub acdirmin: ::c_int,
+        pub acdirmax: ::c_int,
+    }
+
+    pub struct msdosfs_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub mask: ::mode_t,
+        pub flags: ::c_int,
+    }
+
+    pub struct ntfs_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub mode: ::mode_t,
+        pub flag: ::c_ulong,
+    }
+
+    pub struct udf_args {
+        pub fspec: *mut ::c_char,
+        pub lastblock: ::uint32_t,
+    }
+
+    pub struct tmpfs_args {
+        pub ta_version: ::c_int,
+        pub ta_nodes_max: ::ino_t,
+        pub ta_size_max: ::off_t,
+        pub ta_root_uid: ::uid_t,
+        pub ta_root_gid: ::gid_t,
+        pub ta_root_mode: ::mode_t,
+    }
+
+    pub struct fusefs_args {
+        pub name: *mut ::c_char,
+        pub fd: ::c_int,
+        pub max_read: ::c_int,
+        pub allow_other: ::c_int,
+    }
+
+    pub struct xucred {
+        pub cr_uid: ::uid_t,
+        pub cr_gid: ::gid_t,
+        pub cr_ngroups: ::c_short,
+        //https://github.com/openbsd/src/blob/master/sys/sys/syslimits.h#L44
+        pub cr_groups: [::gid_t; 16],
+    }
+
+    pub struct export_args {
+        pub ex_flags: ::c_int,
+        pub ex_root: ::uid_t,
+        pub ex_anon: xucred,
+        pub ex_addr: *mut ::sockaddr,
+        pub ex_addrlen: ::c_int,
+        pub ex_mask: *mut ::sockaddr,
+        pub ex_masklen: ::c_int,
+    }
 }
 
+//https://github.com/openbsd/src/blob/master/sys/sys/mount.h
+pub const ISOFSMNT_NORRIP: ::c_int = 0x1; // disable Rock Ridge Ext
+pub const ISOFSMNT_GENS: ::c_int = 0x2; // enable generation numbers
+pub const ISOFSMNT_EXTATT: ::c_int = 0x4; // enable extended attr
+pub const ISOFSMNT_NOJOLIET: ::c_int = 0x8; // disable Joliet Ext
+pub const ISOFSMNT_SESS: ::c_int = 0x10; // use iso_args.sess
+
+pub const NFS_ARGSVERSION: ::c_int = 4; // change when nfs_args changes
+
+pub const NFSMNT_RESVPORT: ::c_int = 0; // always use reserved ports
+pub const NFSMNT_SOFT: ::c_int = 0x1; // soft mount (hard is default)
+pub const NFSMNT_WSIZE: ::c_int = 0x2; // set write size
+pub const NFSMNT_RSIZE: ::c_int = 0x4; // set read size
+pub const NFSMNT_TIMEO: ::c_int = 0x8; // set initial timeout
+pub const NFSMNT_RETRANS: ::c_int = 0x10; // set number of request retries
+pub const NFSMNT_MAXGRPS: ::c_int = 0x20; // set maximum grouplist size
+pub const NFSMNT_INT: ::c_int = 0x40; // allow interrupts on hard mount
+pub const NFSMNT_NOCONN: ::c_int = 0x80; // Don't Connect the socket
+pub const NFSMNT_NQNFS: ::c_int = 0x100; // Use Nqnfs protocol
+pub const NFSMNT_NFSV3: ::c_int = 0x200; // Use NFS Version 3 protocol
+pub const NFSMNT_KERB: ::c_int = 0x400; // Use Kerberos authentication
+pub const NFSMNT_DUMBTIMR: ::c_int = 0x800; // Don't estimate rtt dynamically
+pub const NFSMNT_LEASETERM: ::c_int = 0x1000; // set lease term (nqnfs)
+pub const NFSMNT_READAHEAD: ::c_int = 0x2000; // set read ahead
+pub const NFSMNT_DEADTHRESH: ::c_int = 0x4000; // set dead server retry thresh
+pub const NFSMNT_NOAC: ::c_int = 0x8000; // disable attribute cache
+pub const NFSMNT_RDIRPLUS: ::c_int = 0x10000; // Use Readdirplus for V3
+pub const NFSMNT_READDIRSIZE: ::c_int = 0x20000; // Set readdir size
+
+/* Flags valid only in mount syscall arguments */
+pub const NFSMNT_ACREGMIN: ::c_int = 0x40000; // acregmin field valid
+pub const NFSMNT_ACREGMAX: ::c_int = 0x80000; // acregmax field valid
+pub const NFSMNT_ACDIRMIN: ::c_int = 0x100000; // acdirmin field valid
+pub const NFSMNT_ACDIRMAX: ::c_int = 0x200000; // acdirmax field valid
+
+/* Flags valid only in kernel */
+pub const NFSMNT_INTERNAL: ::c_int = 0xfffc0000; // Bits set internally
+pub const NFSMNT_HASWRITEVERF: ::c_int = 0x40000; // Has write verifier for V3
+pub const NFSMNT_GOTPATHCONF: ::c_int = 0x80000; // Got the V3 pathconf info
+pub const NFSMNT_GOTFSINFO: ::c_int = 0x100000; // Got the V3 fsinfo
+pub const NFSMNT_MNTD: ::c_int = 0x200000; // Mnt server for mnt point
+pub const NFSMNT_DISMINPROG: ::c_int = 0x400000; // Dismount in progress
+pub const NFSMNT_DISMNT: ::c_int = 0x800000; // Dismounted
+pub const NFSMNT_SNDLOCK: ::c_int = 0x1000000; // Send socket lock
+pub const NFSMNT_WANTSND: ::c_int = 0x2000000; // Want above
+pub const NFSMNT_RCVLOCK: ::c_int = 0x4000000; // Rcv socket lock
+pub const NFSMNT_WANTRCV: ::c_int = 0x8000000; // Want above
+pub const NFSMNT_WAITAUTH: ::c_int = 0x10000000; // Wait for authentication
+pub const NFSMNT_HASAUTH: ::c_int = 0x20000000; // Has authenticator
+pub const NFSMNT_WANTAUTH: ::c_int = 0x40000000; // Wants an authenticator
+pub const NFSMNT_AUTHERR: ::c_int = 0x80000000; // Authentication error
+
+pub const MSDOSFSMNT_SHORTNAME: ::c_int = 0x1; // Force old DOS short names only
+pub const MSDOSFSMNT_LONGNAME: ::c_int = 0x2; // Force Win'95 long names
+pub const MSDOSFSMNT_NOWIN95: ::c_int = 0x4; // Completely ignore Win95 entries
+
+pub const NTFS_MFLAG_CASEINS: ::c_int = 0x1;
+pub const NTFS_MFLAG_ALLNAMES: ::c_int = 0x2;
+
+pub const TMPFS_ARGS_VERSION: ::c_int = 1;
+
 pub const MAP_STACK : ::c_int = 0x4000;
 
 // https://github.com/openbsd/src/blob/master/sys/net/if.h#L187
@@ -59,6 +258,9 @@ extern {
     pub fn strtonum(nptr: *const ::c_char, minval: ::c_longlong,
                     maxval: ::c_longlong,
                     errstr: *mut *const ::c_char) -> ::c_longlong;
+
+    pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int;
+    pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int;
 }
 
 cfg_if! {