Menu

#187 no member named 'st_mtim' in 'struct stat'

autogen
pending
None
1
2020-09-14
2018-07-24
No

autogen 5.18.14 fails to build on macOS High Sierra (10.13), due to this problem:

./expExtract.c:59:47: error: no member named 'st_mtim' in 'struct stat'
        if (time_is_before(outfile_time, stbf.st_mtime))
                                         ~~~~ ^
./autogen.h:428:18: note: expanded from macro 'st_mtime'
#define st_mtime st_mtim
                 ^
./autogen.h:421:21: note: expanded from macro 'time_is_before'
    ((_f).tv_sec < (_s).tv_sec)                 \
                    ^~

I've seen similar errors with other projects.

It builds fine on macOS Sierra (10.12) and OS X El Capitan (10.11).

Discussion

  • Bruce Korb

    Bruce Korb - 2018-07-25
    • status: open --> accepted
    • assigned_to: Bruce Korb
     
  • Bruce Korb

    Bruce Korb - 2018-07-25

    So I need to add a "how is the mod time field spelled" config macro. Lovely. Thank you.

     
  • Bruce Korb

    Bruce Korb - 2018-07-25

    if I could get the structure used by OS/X, I'd appreciate. Thanks.

     
  • Ryan Carsten Schmidt

    On macOS, the stat structure in sys/stat.h contains a reference to __DARWIN_STRUCT_STAT64_TIMES which is defined like this:

    #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
    
    #define __DARWIN_STRUCT_STAT64_TIMES \
        struct timespec st_atimespec;       /* time of last access */ \
        struct timespec st_mtimespec;       /* time of last data modification */ \
        struct timespec st_ctimespec;       /* time of last status change */ \
        struct timespec st_birthtimespec;   /* time of file creation(birth) */
    
    #else /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
    
    #define __DARWIN_STRUCT_STAT64_TIMES \
        time_t      st_atime;       /* [XSI] Time of last access */ \
        long        st_atimensec;       /* nsec of last access */ \
        time_t      st_mtime;       /* [XSI] Last data modification time */ \
        long        st_mtimensec;       /* last data modification nsec */ \
        time_t      st_ctime;       /* [XSI] Time of last status change */ \
        long        st_ctimensec;       /* nsec of last status change */ \
        time_t      st_birthtime;       /*  File creation time(birth)  */ \
        long        st_birthtimensec;   /* nsec of File creation time */
    
    #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
    

    And then outside of the stat structure there is this:

    #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
    #define st_atime st_atimespec.tv_sec
    #define st_mtime st_mtimespec.tv_sec
    #define st_ctime st_ctimespec.tv_sec
    #define st_birthtime st_birthtimespec.tv_sec
    #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
    

    So it looks like depending on the definitions of _POSIX_C_SOURCE and _DARWIN_C_SOURCE, the stat struct might contain an st_mtimespec structure with tv_sec and tv_nsec fields, with st_mtime being a macro referring to the tv_sec field, or stat might directly contain st_mtime and st_mtimensec fields.

    I don't fully understand the implications of setting _POSIX_C_SOURCE or _DARWIN_C_SOURCE, or under what circumstances they might already be set. I know that there are many other places in the system headers where behavior changes depending on those.

    I found an online manpage for stat(2) on Debian Linux where the structures are defined as:

    struct timespec st_atim;
    struct timespec st_mtim;
    struct timespec st_ctim;
    

    And there are macros for accessing these times as seconds:

    #define st_atime             st_atim.tv_sec
    #define st_mtime             st_mtim.tv_sec
    #define st_ctime             st_ctim.tv_sec
    

    I found a manpage for stat(2) on FreeBSD which appers to allow the use of either the st_*tim name or the st_*timespec name, via #defines.

    So, if you just wanted the times in seconds, you should just use st_atime, st_mtime, st_ctime and it will work on any system. But since it looks like your code wants nanoseconds too, you'll have to figure out how to do that on the current platform.

    The asterisk project's code has a method for doing this; perhaps you could adapt it:

    https://github.com/asterisk/asterisk/blob/master/configure.ac#L742

    https://github.com/asterisk/asterisk/blob/master/main/config.c#L1580

    You should probably remove these lines from your code, which redefine st_atime, st_mtime, and st_ctime to have nonstandard meanings:

    #undef  st_atime
    #define st_atime st_atim
    #undef  st_mtime
    #define st_mtime st_mtim
    #undef  st_ctime
    #define st_ctime st_ctim
    
     
  • Hanspeter Niederstrasser

    running ./configure with ac_cv_func_utimensat=no is a workaround to build on 10.13. As I understand it, autogen then builds as it used to on systems with no utimensat.

     
  • Bruce Korb

    Bruce Korb - 2018-08-02

    I am attending to this. I cannot build autogen on Linux at the moment. The autotools suite has made "improvements" to the way it handles compiler generated dependency files. That broke my build because autogen also creates dependency files, but automake's new method is incompatible and the emitted error message is completely inscrutable. Basically, "Oops! Something went wrong and we have no idea" is the message. It takes time. Terribly sorry.

     
  • Bruce Korb

    Bruce Korb - 2018-09-17

    gnulib has this comment in the "stat-time.m4":

    st_atim.tv_nsec - Linux, Solaris, Cygwin

    st_atimespec.tv_nsec - FreeBSD, NetBSD, if ! defined _POSIX_SOURCE

    st_atimensec - FreeBSD, NetBSD, if defined _POSIX_SOURCE

    st_atim.st__tim.tv_nsec - UnixWare (at least 2.1.2 through 7.1)

    So everybody has their own favorite flavor. I'll pull the gnulib stuff.

     
  • Bruce Korb

    Bruce Korb - 2020-09-14
    • status: accepted --> pending
     
  • Bruce Korb

    Bruce Korb - 2020-09-14

    I've updated the code to use the current POSIX specs. This ought to resolve the problem.

     

Log in to post a comment.

MongoDB Logo MongoDB