bartc
2017-08-25 14:11:01 UTC
I wrote that because I don't trust the libc I typically use on Linux
in that respect. My impression is that they want "clean" include
files, and it gets better over time, but I would still not be
surprised to find I had to add an include after the next libc upgrade.
I don't know if this is what you mean, but below follow the standardin that respect. My impression is that they want "clean" include
files, and it gets better over time, but I would still not be
surprised to find I had to add an include after the next libc upgrade.
header files for sys/stat.h for gcc on Windows, and for MSVC (some 280
lines each).
My task had been to duplicate the 'struct stat' contents, as used for
the stat() standard function (as called for a 64-bit implementation of C).
I wasn't able to figure it out from either of these headers. I had to
resort to a program - run under an existing implementation - which
displayed the offsets and sizes of each member of struct stat.
That is really saying something, that C source can be written so messily
that is easier to run a program to find out what it actually means, and
that's just for a struct definition! (I'm not that sure the first of
these even contains the definition of 'struct stat'!)
System headers especially for these big implementations are long overdue
for a overhaul I think. The interface doesn't need to change: the
members of struct stat have standard names.
Perhaps that can also address the issue of why there are so many
stat-like functions that all appear to do the same job.
-------------------------------------------------------------
stat.h for tdm/gcc/mingw/windows
-------------------------------------------------------------
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this
package.
*/
#ifndef _INC_STAT
#define _INC_STAT
#ifndef _WIN32
#error Only Win32 target is supported!
#endif
#include <crtdefs.h>
#include <io.h>
#pragma pack(push,_CRT_PACKING)
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _CRTIMP
#define _CRTIMP __declspec(dllimport)
#endif
#include <sys/types.h>
#ifdef _USE_32BIT_TIME_T
#ifdef _WIN64
#undef _USE_32BIT_TIME_T
#endif
#endif
#ifndef _TIME32_T_DEFINED
typedef long __time32_t;
#define _TIME32_T_DEFINED
#endif
#ifndef _TIME64_T_DEFINED
__MINGW_EXTENSION typedef __int64 __time64_t;
#define _TIME64_T_DEFINED
#endif
#ifndef _TIME_T_DEFINED
#ifdef _USE_32BIT_TIME_T
typedef __time32_t time_t;
#else
typedef __time64_t time_t;
#endif
#define _TIME_T_DEFINED
#endif
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif
#include <_mingw_stat64.h>
#define _S_IFMT 0xF000
#define _S_IFDIR 0x4000
#define _S_IFCHR 0x2000
#define _S_IFIFO 0x1000
#define _S_IFREG 0x8000
#define _S_IREAD 0x0100
#define _S_IWRITE 0x0080
#define _S_IEXEC 0x0040
_CRTIMP int __cdecl _fstat32(int _FileDes,struct _stat32 *_Stat);
_CRTIMP int __cdecl _stat32(const char *_Name,struct _stat32 *_Stat);
_CRTIMP int __cdecl _fstat64(int _FileDes,struct _stat64 *_Stat);
_CRTIMP int __cdecl _fstat32i64(int _FileDes,struct _stat32i64 *_Stat);
int __cdecl _fstat64i32(int _FileDes,struct _stat64i32 *_Stat);
#ifndef __CRT__NO_INLINE
__CRT_INLINE int __cdecl _fstat64i32(int _FileDes,struct _stat64i32
*_Stat)
{
struct _stat64 st;
int ret=_fstat64(_FileDes,&st);
if (ret == -1) {
memset(_Stat,0,sizeof(struct _stat64i32));
return -1;
}
_Stat->st_dev=st.st_dev;
_Stat->st_ino=st.st_ino;
_Stat->st_mode=st.st_mode;
_Stat->st_nlink=st.st_nlink;
_Stat->st_uid=st.st_uid;
_Stat->st_gid=st.st_gid;
_Stat->st_rdev=st.st_rdev;
_Stat->st_size=(_off_t) st.st_size;
_Stat->st_atime=st.st_atime;
_Stat->st_mtime=st.st_mtime;
_Stat->st_ctime=st.st_ctime;
return ret;
}
#endif /* __CRT__NO_INLINE */
_CRTIMP int __cdecl _stat64(const char *_Name,struct _stat64 *_Stat);
_CRTIMP int __cdecl _stat32i64(const char *_Name,struct _stat32i64
*_Stat);
int __cdecl _stat64i32(const char *_Name,struct _stat64i32 *_Stat);
#ifndef __CRT__NO_INLINE
__CRT_INLINE int __cdecl _stat64i32(const char *_Name,struct
_stat64i32 *_Stat)
{
struct _stat64 st;
int ret=_stat64(_Name,&st);
if (ret == -1) {
memset(_Stat,0,sizeof(struct _stat64i32));
return -1;
}
_Stat->st_dev=st.st_dev;
_Stat->st_ino=st.st_ino;
_Stat->st_mode=st.st_mode;
_Stat->st_nlink=st.st_nlink;
_Stat->st_uid=st.st_uid;
_Stat->st_gid=st.st_gid;
_Stat->st_rdev=st.st_rdev;
_Stat->st_size=(_off_t) st.st_size;
_Stat->st_atime=st.st_atime;
_Stat->st_mtime=st.st_mtime;
_Stat->st_ctime=st.st_ctime;
return ret;
}
#endif /* __CRT__NO_INLINE */
#ifndef _WSTAT_DEFINED
#define _WSTAT_DEFINED
_CRTIMP int __cdecl _wstat32(const wchar_t *_Name,struct _stat32 *_Stat);
_CRTIMP int __cdecl _wstat32i64(const wchar_t *_Name,struct
_stat32i64 *_Stat);
int __cdecl _wstat64i32(const wchar_t *_Name,struct _stat64i32 *_Stat);
_CRTIMP int __cdecl _wstat64(const wchar_t *_Name,struct _stat64 *_Stat);
#endif
#ifndef NO_OLDNAMES
#define _S_IFBLK 0x3000 /* Block: Is this ever set under w32? */
#define S_IFMT _S_IFMT
#define S_IFDIR _S_IFDIR
#define S_IFCHR _S_IFCHR
#define S_IFREG _S_IFREG
#define S_IREAD _S_IREAD
#define S_IWRITE _S_IWRITE
#define S_IEXEC _S_IEXEC
#define S_IFIFO _S_IFIFO
#define S_IFBLK _S_IFBLK
#define _S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC)
#define _S_IXUSR _S_IEXEC
#define _S_IWUSR _S_IWRITE
#define S_IRWXU _S_IRWXU
#define S_IXUSR _S_IXUSR
#define S_IWUSR _S_IWUSR
#define S_IRUSR _S_IRUSR
#define _S_IRUSR _S_IREAD
#define S_IRGRP (S_IRUSR >> 3)
#define S_IWGRP (S_IWUSR >> 3)
#define S_IXGRP (S_IXUSR >> 3)
#define S_IRWXG (S_IRWXU >> 3)
#define S_IROTH (S_IRGRP >> 3)
#define S_IWOTH (S_IWGRP >> 3)
#define S_IXOTH (S_IXGRP >> 3)
#define S_IRWXO (S_IRWXG >> 3)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#if !defined (RC_INVOKED) && !defined (NO_OLDNAMES)
int __cdecl stat(const char *_Filename,struct stat *_Stat);
int __cdecl fstat(int _Desc,struct stat *_Stat);
int __cdecl wstat(const wchar_t *_Filename,struct stat *_Stat);
#ifndef __CRT__NO_INLINE
#ifdef _USE_32BIT_TIME_T
__CRT_INLINE int __cdecl
fstat(int _Desc,struct stat *_Stat) {
struct _stat32 st;
int ret=_fstat32(_Desc,&st);
if (ret == -1) {
memset(_Stat,0,sizeof(struct stat));
return -1;
}
/* struct stat and struct _stat32
are the same for this case. */
memcpy(_Stat, &st, sizeof(struct _stat32));
return ret;
}
/* Disable it for making sure trailing slash issue is fixed. */
#if 0
__CRT_INLINE int __cdecl
stat(const char *_Filename,struct stat *_Stat) {
struct _stat32 st;
int ret=_stat32(_Filename,&st);
if (ret == -1) {
memset(_Stat,0,sizeof(struct stat));
return -1;
}
/* struct stat and struct _stat32
are the same for this case. */
memcpy(_Stat, &st, sizeof(struct _stat32));
return ret;
}
#endif
#else
__CRT_INLINE int __cdecl
fstat(int _Desc,struct stat *_Stat) {
struct _stat64 st;
int ret=_fstat64(_Desc,&st);
if (ret == -1) {
memset(_Stat,0,sizeof(struct stat));
return -1;
}
/* struct stat and struct _stat64i32
are the same for this case. */
_Stat->st_dev=st.st_dev;
_Stat->st_ino=st.st_ino;
_Stat->st_mode=st.st_mode;
_Stat->st_nlink=st.st_nlink;
_Stat->st_uid=st.st_uid;
_Stat->st_gid=st.st_gid;
_Stat->st_rdev=st.st_rdev;
_Stat->st_size=(_off_t) st.st_size;
_Stat->st_atime=st.st_atime;
_Stat->st_mtime=st.st_mtime;
_Stat->st_ctime=st.st_ctime;
return ret;
}
/* Disable it for making sure trailing slash issue is fixed. */
#if 0
__CRT_INLINE int __cdecl
stat(const char *_Filename,struct stat *_Stat) {
struct _stat64 st;
int ret=_stat64(_Filename,&st);
if (ret == -1) {
memset(_Stat,0,sizeof(struct stat));
return -1;
}
/* struct stat and struct _stat64i32
are the same for this case. */
_Stat->st_dev=st.st_dev;
_Stat->st_ino=st.st_ino;
_Stat->st_mode=st.st_mode;
_Stat->st_nlink=st.st_nlink;
_Stat->st_uid=st.st_uid;
_Stat->st_gid=st.st_gid;
_Stat->st_rdev=st.st_rdev;
_Stat->st_size=(_off_t) st.st_size;
_Stat->st_atime=st.st_atime;
_Stat->st_mtime=st.st_mtime;
_Stat->st_ctime=st.st_ctime;
return ret;
}
#endif
#endif /* _USE_32BIT_TIME_T */
#endif /* __CRT__NO_INLINE */
#endif /* !RC_INVOKED && !NO_OLDNAMES */
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
#ifdef _USE_32BIT_TIME_T
#define stat _stat32i64
#define fstat _fstat32i64
#else
#define stat _stat64
#define fstat _fstat64
#endif
#endif
#ifdef __cplusplus
}
#endif
#pragma pack(pop)
#endif /* _INC_STAT */
---------------------------------------------------------
stat.h for MSVC Windows
---------------------------------------------------------
/***
*sys/stat.h - defines structure used by stat() and fstat()
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* This file defines the structure used by the _stat() and _fstat()
* routines.
* [System V]
*
* [Public]
*
****/
#if _MSC_VER > 1000
#pragma once
#endif
#ifndef _INC_STAT
#define _INC_STAT
#if !defined(_WIN32)
#error ERROR: Only Win32 target supported!
#endif
#include <crtdefs.h>
#ifdef _MSC_VER
#pragma pack(push,_CRT_PACKING)
#endif /* _MSC_VER */
#ifdef __cplusplus
extern "C" {
#endif
/* Define _CRTIMP */
#ifndef _CRTIMP
#ifdef _DLL
#define _CRTIMP __declspec(dllimport)
#else /* ndef _DLL */
#define _CRTIMP
#endif /* _DLL */
#endif /* _CRTIMP */
/* Define __cdecl for non-Microsoft compilers */
#if ( !defined(_MSC_VER) && !defined(__cdecl) )
#define __cdecl
#endif
#include <sys/types.h>
#if !defined(_W64)
#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER
= 1300
#define _W64 __w64#else
#define _W64
#endif
#endif
#ifdef _USE_32BIT_TIME_T
#ifdef _WIN64
#include <crtwrn.h>
#pragma _CRT_WARNING( _NO_32BIT_TIME_T )
#undef _USE_32BIT_TIME_T
#endif
#endif
#ifndef _TIME32_T_DEFINED
typedef _W64 long __time32_t; /* 32-bit time value */
#define _TIME32_T_DEFINED
#endif
#ifndef _TIME64_T_DEFINED
typedef __int64 __time64_t; /* 64-bit time value */
#define _TIME64_T_DEFINED
#endif
#ifndef _TIME_T_DEFINED
#ifdef _USE_32BIT_TIME_T
typedef __time32_t time_t; /* time value */
#else
typedef __time64_t time_t; /* time value */
#endif
#define _TIME_T_DEFINED /* avoid multiple def's of time_t */
#endif
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif
/* define structure for returning status information */
#ifndef _STAT_DEFINED
struct _stat32 {
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
_off_t st_size;
__time32_t st_atime;
__time32_t st_mtime;
__time32_t st_ctime;
};
#if !__STDC__
/* Non-ANSI names for compatibility */
struct stat {
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
_off_t st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
};
#endif /* __STDC__ */
struct _stat32i64 {
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
__int64 st_size;
__time32_t st_atime;
__time32_t st_mtime;
__time32_t st_ctime;
};
struct _stat64i32 {
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
_off_t st_size;
__time64_t st_atime;
__time64_t st_mtime;
__time64_t st_ctime;
};
struct _stat64 {
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
__int64 st_size;
__time64_t st_atime;
__time64_t st_mtime;
__time64_t st_ctime;
};
/*
* We have to have same name for structure and the fuction so as to do the
* macro magic.we need the structure name and function name the same.
*/
#define __stat64 _stat64
#ifdef _USE_32BIT_TIME_T
#define _fstat _fstat32
#define _fstati64 _fstat32i64
#define _stat _stat32
#define _stati64 _stat32i64
#define _wstat _wstat32
#define _wstati64 _wstat32i64
#else
#define _fstat _fstat64i32
#define _fstati64 _fstat64
#define _stat _stat64i32
#define _stati64 _stat64
#define _wstat _wstat64i32
#define _wstati64 _wstat64
#endif
#define _STAT_DEFINED
#endif
#define _S_IFMT 0xF000 /* file type mask */
#define _S_IFDIR 0x4000 /* directory */
#define _S_IFCHR 0x2000 /* character special */
#define _S_IFIFO 0x1000 /* pipe */
#define _S_IFREG 0x8000 /* regular */
#define _S_IREAD 0x0100 /* read permission, owner */
#define _S_IWRITE 0x0080 /* write permission, owner */
#define _S_IEXEC 0x0040 /* execute/search permission,
owner */
/* Function prototypes */
_CRTIMP int __cdecl _fstat32(_In_ int _FileDes, _Out_ struct _stat32 *
_Stat);
_CRTIMP int __cdecl _stat32(_In_z_ const char * _Name, _Out_ struct
_stat32 * _Stat);
_CRTIMP int __cdecl _fstat32i64(_In_ int _FileDes, _Out_ struct
_stat32i64 * _Stat);
_CRTIMP int __cdecl _fstat64i32(_In_ int _FileDes, _Out_ struct
_stat64i32 * _Stat);
_CRTIMP int __cdecl _fstat64(_In_ int _FileDes, _Out_ struct _stat64 *
_Stat);
_CRTIMP int __cdecl _stat32i64(_In_z_ const char * _Name, _Out_ struct
_stat32i64 * _Stat);
_CRTIMP int __cdecl _stat64i32(_In_z_ const char * _Name, _Out_ struct
_stat64i32 * _Stat);
_CRTIMP int __cdecl _stat64(_In_z_ const char * _Name, _Out_ struct
_stat64 * _Stat);
#ifndef _WSTAT_DEFINED
/* also declared in wchar.h */
_CRTIMP int __cdecl _wstat32(_In_z_ const wchar_t * _Name, _Out_ struct
_stat32 * _Stat);
_CRTIMP int __cdecl _wstat32i64(_In_z_ const wchar_t * _Name, _Out_
struct _stat32i64 * _Stat);
_CRTIMP int __cdecl _wstat64i32(_In_z_ const wchar_t * _Name, _Out_
struct _stat64i32 * _Stat);
_CRTIMP int __cdecl _wstat64(_In_z_ const wchar_t * _Name, _Out_ struct
_stat64 * _Stat);
#define _WSTAT_DEFINED
#endif
#if !__STDC__
/* Non-ANSI names for compatibility */
#define S_IFMT _S_IFMT
#define S_IFDIR _S_IFDIR
#define S_IFCHR _S_IFCHR
#define S_IFREG _S_IFREG
#define S_IREAD _S_IREAD
#define S_IWRITE _S_IWRITE
#define S_IEXEC _S_IEXEC
#endif /* __STDC__ */
/*
* This file is included for __inlined non stdc functions. i.e. stat
and fstat
*/
#if !defined(RC_INVOKED) && !defined(__midl)
#include <sys/stat.inl>
#endif
#ifdef __cplusplus
}
#endif
#ifdef _MSC_VER
#pragma pack(pop)
#endif /* _MSC_VER */
#endif /* _INC_STAT */
--
bartc
bartc