Skip to content

libc's struct Stat is defined incorrectly on 64-bit FreeBSD #25155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
aidancully opened this issue May 6, 2015 · 1 comment
Closed

libc's struct Stat is defined incorrectly on 64-bit FreeBSD #25155

aidancully opened this issue May 6, 2015 · 1 comment

Comments

@aidancully
Copy link
Contributor

blksize_t on 64-bit FreeBSD is 32 bits, not 64.

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stddef.h>

#define pr_field_offset(field) \
  do { printf(# field ": %d\n", offsetof(struct stat, field)); } while (0)

int main(int argc, char *argv[])
{
  printf("%d\n", sizeof(struct stat));
  pr_field_offset(st_dev);
  pr_field_offset(st_size);
  pr_field_offset(st_blocks);
  pr_field_offset(st_blksize);
  pr_field_offset(st_flags);
  pr_field_offset(st_gen);
  pr_field_offset(st_birthtim);
  return 0;
}

on FreeBSD x86_64 yields:

120
st_dev: 0
st_size: 72
st_blocks: 80
st_blksize: 88
st_flags: 92
st_gen: 96
st_birthtim: 104
#![feature(libc)]
extern crate libc;

macro_rules! containerof_field_offset {
    ($container:ty : $field:ident) => (unsafe {
        &(*(0usize as *const $container)).$field as *const _ as usize
    })
}
macro_rules! pr_field_offsets {
  ( $( $field:ident ),* ) => (unsafe {
    $(
      println!("{}: {}", stringify!($field), containerof_field_offset!(libc::stat : $field));
    )*
  })
}

fn main() {
  println!("{}", std::mem::size_of::<libc::stat>());
  pr_field_offsets!(st_dev, st_ino, st_mode, st_nlink, st_uid, st_gid, st_rdev, st_atime, st_atime_nsec);
  pr_field_offsets!(st_atime, st_atime_nsec, st_mtime, st_mtime_nsec, st_ctime, st_ctime_nsec);
  pr_field_offsets!(st_size, st_blocks, st_blksize, st_flags, st_gen, st_lspare, st_birthtime, st_birthtime_nsec);
  pr_field_offsets!(__unused);
}

yields:

$ ./test
136
st_dev: 0
st_ino: 4
st_mode: 8
st_nlink: 10
st_uid: 12
st_gid: 16
st_rdev: 20
st_atime: 24
st_atime_nsec: 32
st_atime: 24
st_atime_nsec: 32
st_mtime: 40
st_mtime_nsec: 48
st_ctime: 56
st_ctime_nsec: 64
st_size: 72
st_blocks: 80
st_blksize: 88
st_flags: 96
st_gen: 100
st_lspare: 104
st_birthtime: 112
st_birthtime_nsec: 120
__unused: 128

I tracked this down to the blksize_t type definition, which is unconditionally 32-bit on FreeBSD (see here, noting this line:

typedef __uint32_t      __blksize_t;    /* file block size */

this is unconditionally the definition of __blksize_t on FreeBSD - whether on 32-bit or 64-bit platform.)

@aidancully
Copy link
Contributor Author

Also, __unused is a no-op (two fields of size 0) on 64-bit FreeBSD, the __unused field can be deleted from the structure.

bors added a commit that referenced this issue Feb 18, 2016

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
In #25155 the os::freebsd::raw stat was split for the x86 vs. x86-64 cases, which appears to have been done to implement the padding on the end of struct stat for the x86 case (the struct is otherwise the same notwistanding the size of long).

This PR de-duplicates the struct using #[cfg(target_arch = "x86")] for the __unused field, which also fixes the definitions which had sinced changed with the LFS work d088b67.

Also changed definitions to c_long for dragonfly and freebsd where appropriate.

Also removes some unused imports that the compiler was complaining about.

dragonfly's long time_t:
https://gitweb.dragonflybsd.org/dragonfly.git/blob/a2a57c243ff8016578bc559f8603fb25bbcf1768:/lib/libstand/machine/stdint.h

freebsd's long time_t:
https://svnweb.freebsd.org/base/release/10.1.0/sys/x86/include/_types.h?view=markup
https://github.com/rust-lang/rust/blob/d088b671872f1df6993ccca6fa6139ebed0a8cf3/src/liblibc/lib.rs#L980

freebsd's padding for i686 stat:
https://svnweb.freebsd.org/base/release/10.1.0/sys/sys/stat.h?view=markup#l139
https://github.com/rust-lang/rust/blob/d088b671872f1df6993ccca6fa6139ebed0a8cf3/src/liblibc/lib.rs#L1038
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants