/*****************************************************************************\ * * * Filename: stat.h * * * * Description: MsvcLibX extensions to sys/stat.h. * * * * Notes: * * * * History: * * 2014-02-06 JFL Moved stat extensions from dirent.h. * * 2014-02-26 JFL Added proprietary routines for managing file times. * * 2014-03-24 JFL Added a mechanism to also include MSVC's own sys/stat.h. * * Renamed this file from statx.h to sys/stat.h. * * 2014-05-27 JFL Added dummy definitions for S_TYPEISSHM() & S_TYPEISTMO().* * 2014-06-03 JFL Moved struct timespec definition to sys/time.h. * * 2014-06-06 JFL Moved mode_t & off*_t definition to sys/types.h. * * Moved fseeko* & ftello* functions definitions to stdio.h. * * 2014-06-24 JFL Added fstat and fstat64 external references. * * 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT. * 2016-09-15 JFL Fixed a warning in Visual Studio 2015. * * * * Copyright 2016 Hewlett Packard Enterprise Development LP * * Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * \*****************************************************************************/ #ifndef _MSVCLIBX_STAT_H #define _MSVCLIBX_STAT_H 1 #include "msvclibx.h" #include #include UCRT_INCLUDE_FILE(sys\stat.h) /* Include MSVC's own file */ #include /* For dirent2stat() arguments definitions */ #include /* for time_t definition */ #include /* for timespec definition */ /* Include MsvcLibX's override, to avoid conflict with the standard mkdir defined here, should be manually included later on in the C source */ #include #ifdef __cplusplus extern "C" { #endif /************************ MS-DOS-specific definitions ************************/ #ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */ /* Define stat and fstat to use 32 or 64 file lengths, as defined by _FILE_OFFSET_BITS */ /* #undef stat /* Not normally defined by MSVC */ /* #undef fstat /* Not normally defined by MSVC */ #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) /* TO DO: Windows 95 has extended functions for handling 64-bits files sizes */ #else #endif /* For now, use the MSVC 32-bits functions in all cases */ #define stat _stat #define fstat _fstat #define lstat stat /* Define standard 64-bits structures and functions */ #if defined(_LARGEFILE_SOURCE64) /* For now, hide the fact that DOS does not support 64-bits lengths */ #define off64_t _off_t #define stat64 _stat #define fstat64 _fstat #define lstat64 stat64 #endif /* Proprietary function for recovering available infos without calling stat */ extern int dirent2stat(struct dirent *pDE, struct _stat *pStat); #define dirent2stat64 dirent2stat /* The current versions are the same */ #define _DIRENT2STAT_DEFINED 1 /* MS-DOS always reports local file times. MsvcLibX DOS version generates a pseudo GMT time for files using mktime(), which can then be undone by localtime(). */ #define LocalFileTime localtime /* Proprietary function for converting a DOS date/time to a Posix time_t */ extern time_t Filetime2Timet(uint16_t date, uint16_t time); /* Proprietary function for generating a string with the local file time, in the ISO 8601 date/time format */ extern char *Filetime2String(uint16_t date, uint16_t time, char *pBuf, size_t nBufSize); #endif /* defined(_MSDOS) */ /************************ Win32-specific definitions *************************/ #ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ /* Visual C++ sys/stat.h defines a series of _statXY functions and structures: XY = 32 st_*time is 32-bits __time32_t & st_size is 32-bits _off_t XY = 32i64 st_*time is 32-bits __time32_t & st_size is 64-bits __int64 XY = 64i32 st_*time is 64-bits __time64_t & st_size is 32-bits _off_t XY = 64 st_*time is 64-bits __time64_t & st_size is 64-bits __int64 Then it defines additional _statZ macros generating _statXY, based on: XY = 32 if _USE_32BIT_TIME_T defined & Z is "" XY = 32i64 if _USE_32BIT_TIME_T defined & Z is i64 XY = 64i32 if _USE_32BIT_TIME_T undefined & Z is "" XY = 64 if _USE_32BIT_TIME_T undefined & Z is i64 Special case: In 64-bits windows, _USE_32BIT_TIME_T defined is ignored and #undef(ined) */ /* Define stat and fstat to use 32 or 64 file lengths, as defined by _FILE_OFFSET_BITS */ /* #undef stat /* Not normally defined by MSVC */ /* #undef fstat /* Not normally defined by MSVC */ #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) #define _STAT_FILE_SIZE 64 #define _STAT_SUFFIX i64 #else #define _STAT_FILE_SIZE 32 #define _STAT_SUFFIX #endif #define _USE_EXTENDED_STAT_STRUCT 1 #define _VALUEOF(a) a /* Get the token value */ #define _CONCAT2T(a,b) a##b /* Concatenate two tokens (does not expand their values) */ #define _CONCAT3T(a,b,c) a##b##c /* Concatenate three tokens (does not expand their values) */ #define _CONCAT4T(a,b,c,d) a##b##c##d /* Concatenate four tokens (does not expand their values) */ #define _CONCAT(a,b) _CONCAT2T(a,b) /* Concatenate two tokens values */ #define _CONCAT3(a,b,c) _CONCAT3T(a,b,c) /* Concatenate three tokens values */ #define _CONCAT4(a,b,c,d) _CONCAT4T(a,b,c,d) /* Concatenate four tokens values */ #define _CON_STAT_CAT1(pre,post) pre##stat##post #define _CON_STAT_CAT(pre,post) _CON_STAT_CAT1(pre,post) /* Define what stat, fstat, lstat, stat64 macros would be, if we were to use MSVC's own stat structures and routines */ /* Avoid concatenating tokens _stat and _fstat, as these are already macros that would be expanded, and we do not want this as this stage. */ #define _MSVC_stat _CON_STAT_CAT(_ , _STAT_SUFFIX) #define _MSVC_fstat _CON_STAT_CAT(_f, _STAT_SUFFIX) #define _MSVC_lstat _CON_STAT_CAT(_l, _STAT_SUFFIX) #define _MSVC_stat64 _CON_STAT_CAT(_ , i64) #define _MSVC_lstat64 _CON_STAT_CAT(_l, i64) #ifdef _USE_32BIT_TIME_T #define _lstat _lstat32 #define _lstati64 _lstat32i64 #define _lstat_ns _lstat32_ns #define _lstati64_ns _lstat32i64_ns #else #define _lstat _lstat64i32 #define _lstati64 _lstat64 #define _lstat_ns _lstat64i32_ns #define _lstati64_ns _lstat64_ns #endif #if !_USE_EXTENDED_STAT_STRUCT #define _NS_SUFFIX #else /* _USE_EXTENDED_STAT_STRUCT */ #define _MSVCLIBX_STAT_DEFINED 1 #define _NS_SUFFIX _ns /* Define what stat, fstat, lstat, stat64 macros and structures would be, if we were to use MsvcLibX extended stat structures and routines */ #define _LIBX_stat _CONCAT(_MSVC_stat,_ns) #define _LIBX_stat64 _CONCAT(_MSVC_stat64,_ns) #include "debugm.h" #pragma message("Defining type struct " VALUEIZE(_LIBX_stat)) struct _LIBX_stat { /* MSVC standard stat structure fields */ _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; /* End of MSVC standard stat structure fields */ struct timespec st_ctim; /* File creation date/time, w. ns resolution */ struct timespec st_mtim; /* File modification date/time, w. ns resolution */ struct timespec st_atim; /* File access date/time, w. ns resolution */ unsigned int st_Win32Attrs; /* Win32 file attributes */ unsigned int st_ReparseTag; /* Reparse point tag */ }; /* Compatibility with old Unix fields */ #define st_ctime st_ctim.tv_sec #define st_mtime st_mtim.tv_sec #define st_atime st_atim.tv_sec /* Compatibility with intermediate Unix fields */ #define st_ctimensec st_ctim.tv_nsec /* Nanosecond part of the file creation time */ #define st_mtimensec st_mtim.tv_nsec /* Nanosecond part of the file modification time */ #define st_atimensec st_atim.tv_nsec /* Nanosecond part of the file access time */ #if (_STAT_FILE_SIZE != 64) /* Else it's the same as struct stat */ #pragma message("Defining type struct " VALUEIZE(_LIBX_stat64)) struct _LIBX_stat64 { /* MSVC standard stat structure fields */ _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; off64_t st_size; /* End of MSVC standard stat structure fields */ struct timespec st_ctim; /* File creation date/time, w. ns resolution */ struct timespec st_mtim; /* File modification date/time, w. ns resolution */ struct timespec st_atim; /* File access date/time, w. ns resolution */ unsigned int st_Win32Attrs; /* Win32 file attributes */ unsigned int st_ReparseTag; /* Reparse point tag */ }; #endif #endif /* !_USE_EXTENDED_STAT_STRUCT */ /* Define standard stat, fstat, lstat macros */ #define stat _CONCAT(_MSVC_stat,_NS_SUFFIX) #define fstat _CONCAT(_MSVC_fstat,_NS_SUFFIX) #define lstat _CONCAT(_MSVC_lstat,_NS_SUFFIX) /* Reference standard stat, fstat, lstat functions that we redefine */ #if _USE_EXTENDED_STAT_STRUCT /* Else we'll use MSVC's version */ extern int stat(const char *path, struct stat *buf); extern int fstat(int nFile, struct stat *buf); #endif extern int lstat(const char *path, struct stat *buf); /* Define standard 64-bits macros and functions */ #if defined(_LARGEFILE_SOURCE64) #define stat64 _CONCAT(_stati64,_NS_SUFFIX) #define fstat64 _CONCAT(_fstati64,_NS_SUFFIX) #define lstat64 _CONCAT(_lstati64,_NS_SUFFIX) #if (_STAT_FILE_SIZE != 64) /* Else they're the same as functions stat & lstat */ #if _USE_EXTENDED_STAT_STRUCT /* Else we'll use MSVC's version */ extern int stat64(const char *path, struct stat64 *buf); extern int fstat64(int nFile, struct stat *buf); #endif extern int lstat64(const char *path, struct stat64 *buf); #endif #endif /* Proprietary function for recovering dirent infos without calling stat */ /* Note: MSDOS has a single stat version, and its dirent2stat implementation is in dirent.c */ #ifdef _USE_32BIT_TIME_T #if (_STAT_FILE_SIZE != 64) /* Else if _STAT_FILE_SIZE=64, then struct _stat32_ns isn't defined */ extern int _CONCAT(_dirent2_stat32,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat32,_NS_SUFFIX) *pStat); #endif extern int _CONCAT(_dirent2_stat32i64,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat32i64,_NS_SUFFIX) *pStat); #else #if (_STAT_FILE_SIZE != 64) /* Else if _STAT_FILE_SIZE=64, then struct _stat64i32_ns isn't defined */ extern int _CONCAT(_dirent2_stat64i32,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat64i32,_NS_SUFFIX) *pStat); #endif extern int _CONCAT(_dirent2_stat64,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat64,_NS_SUFFIX) *pStat); #endif #define dirent2stat _CONCAT(_dirent2,stat) #define _DIRENT2STAT_DEFINED 1 #define unlink _CONCAT(_unlink_, stat) #define rmdir _CONCAT(_rmdir_, stat) extern int unlink(const char *path); extern int rmdir(const char *path); /* Proprietary function for generating a printable local file time, using Windows' specific algorithm, to match cmd.exe dir output. */ extern struct tm *LocalFileTime(const time_t *pt); /* Proprietary function for converting a Win32 FILETIME to a Posix time_t */ extern time_t Filetime2Timet(const FILETIME *pFT); /* Proprietary function for converting a Posix time_t to a Win32 FILETIME */ extern void Timet2Filetime(time_t s, FILETIME *pFT); /* Proprietary function for converting a Win32 FILETIME to a Posix {time_t,nanosecond} */ extern void Filetime2Timespec(const FILETIME *pFT, struct timespec *pTS); /* Proprietary function for converting a Posix {time_t,nanosecond} to a Win32 FILETIME */ extern void Timespec2Filetime(const struct timespec *pTS, FILETIME *pFT); /* Proprietary function for generating a string with the local file time, in the ISO 8601 date/time format */ extern char *Filetime2String(const FILETIME *pFT, char *pBuf, size_t nBufSize); #endif /* defined(_WIN32) */ /************************* OS/2-specific definitions *************************/ #ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */ /* Define stat and fstat to use 32 or 64 file lengths, as defined by _FILE_OFFSET_BITS */ /* #undef stat /* Not normally defined by MSVC */ /* #undef fstat /* Not normally defined by MSVC */ #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) /* TO DO: Windows 95 has extended functions for handling 64-bits files sizes */ #else #endif /* For now, use the MSVC 32-bits functions in all cases */ #define off_t _off_t #define stat _stat #define fstat _fstat #define lstat stat /* Define standard 64-bits functions */ #if defined(_LARGEFILE_SOURCE64) /* For now, hide the fact that DOS does not support 64-bits lengths */ #define off64_t _off_t #define stat64 _stat #define fstat64 _fstat #define lstat64 stat64 #endif /* Proprietary function for recovering available infos without calling stat */ /* extern int dirent2stat(struct dirent *pDE, struct _stat *pStat); */ /* #define dirent2stat64 dirent2stat /* The current versions are the same */ /* #define _DIRENT2STAT_DEFINED 1 */ /* To do: Check if OS/2 uses local or GMT times, and implement LocalFileTime() if needed. */ #define LocalFileTime localtime #endif /* defined(_OS2) */ /********************** End of OS-specific definitions ***********************/ #define lchmod chmod /* MSVC is buggy and chmod() applies to the link itself */ /* Structure stat standard st_mode values not defined in DOS/Windows' sys/stat.h */ /* Must match the d_type field types in dirent.h. */ /* #define S_IFMT 0xF000 /* Mask for the 4-bit file type */ #define S_IFIFO 0x1000 /* FIFO */ /* #define S_IFCHR 0x2000 /* Character device */ /* #define S_IFDIR 0x4000 /* Directory */ #define S_IFBLK 0x6000 /* Block device */ /* #define S_IFREG 0x8000 /* Regular file */ #define S_IFLNK 0xA000 /* Symbolic link */ #define S_IFSOCK 0xC000 /* Socket */ /* Structure stat standard st_mode type test macros */ /* The existence of these macros can be used to test for the OS support of the feature */ #define S_ISTYPE(m, TYPE) ((m & S_IFMT) == TYPE) /* Both DOS and Windows support these file types */ #define S_ISCHR(m) S_ISTYPE(m, S_IFCHR) /* Test for a character device */ #define S_ISDIR(m) S_ISTYPE(m, S_IFDIR) /* Test for a directory */ #define S_ISREG(m) S_ISTYPE(m, S_IFREG) /* Test for a regular file */ #ifdef _WIN32 /* Only Windows supports these */ #define S_ISLNK(m) S_ISTYPE(m, S_IFLNK) /* Test for a symbolic link */ #endif #if 0 /* Only Unix supports these? At least MsvcLibX does not support them now. */ #define S_ISBLK(m) S_ISTYPE(m, S_IFBLK) /* Test for a block device */ #define S_ISFIFO(m) S_ISTYPE(m, S_IFIFO) /* Test for a pipe or FIFO */ #define S_ISSOCK(m) S_ISTYPE(m, S_IFSOCK) /* Test for a socket */ #endif #define S_ISBLK(m) 0 /* Test for a block device */ #define S_ISCTG(m) 0 /* Test for a high performance ("contiguous data") file */ #define S_ISDOOR(m) 0 /* Test for a door */ #define S_ISFIFO(m) 0 /* Test for a pipe or FIFO */ #define S_ISMPB(m) 0 /* Test for a multiplexed block device */ #define S_ISMPC(m) 0 /* Test for a multiplexed character device */ #define S_ISNWK(m) 0 /* Test for a network special file (HP-UX) */ #define S_ISPORT(m) 0 /* Test for a port */ #define S_ISSOCK(m) 0 /* Test for a socket */ #define S_ISWHT(m) 0 /* Test for a whiteout (4.4BSD) */ /* Other optional file types that some operating systems support */ #define S_TYPEISMQ(pStat) 0 /* Test for a message queue */ #define S_TYPEISSEM(pStat) 0 /* Test for a semaphore */ #define S_TYPEISSHM(pStat) 0 /* Test for a shared memory object */ #define S_TYPEISTMO(pStat) 0 /* Test for a typed memory object */ /* Structure stat standard st_mode flags */ #define S_ISUID 04000 /* Set UID bit */ #define S_ISGID 02000 /* Set-group-ID bit */ #define S_ISVTX 01000 /* Sticky bit */ #define S_IRWXU 0700 /* Mask for file owner permissions */ #define S_IRUSR 0400 /* Owner has read permission. Alias S_IREAD */ #define S_IWUSR 0200 /* Owner has write permission. Alias S_IWRITE */ #define S_IXUSR 0100 /* Owner has execute permission. Alias S_IEXEC */ #define S_IRWXG 070 /* Mask for group permissions */ #define S_IRGRP 040 /* Group has read permission */ #define S_IWGRP 020 /* Group has write permission */ #define S_IXGRP 010 /* Group has execute permission */ #define S_IRWXO 07 /* Mask for permissions for others (not in group) */ #define S_IROTH 04 /* Others have read permission */ #define S_IWOTH 02 /* Others have write permission */ #define S_IXOTH 01 /* Others have execute permission */ #define S_IRWXUGO 00777 /* S_IRWXU|S_IRWXG|S_IRWXO */ #define S_IALLUGO 07777 /* S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO */ #define S_IRUGO 00444 /* S_IRUSR|S_IRGRP|S_IROTH */ #define S_IWUGO 00222 /* S_IWUSR|S_IWGRP|S_IWOTH */ #define S_IXUGO 00111 /* S_IXUSR|S_IXGRP|S_IXOTH */ /* Structure stat extensions for DOS/Windows file attributes */ #define S_IFVOLID 0xF000 /* Volume ID pseudo-file, defined in FAT root dir */ #define S_ISVOLID(m) S_ISTYPE(m, S_IFVOLID) /* Test for a FAT volume ID */ #define S_HIDDEN 01 /* Reuse permissions bit not used in DOS/Windows */ #define S_ARCHIVE 02 /* Reuse permissions bit not used in DOS/Windows */ #define S_SYSTEM 04 /* Reuse permissions bit not used in DOS/Windows */ #define S_COMPRESSED 010 /* Reuse permissions bit not used in DOS/Windows */ #define S_ENCRYPTED 020 /* Reuse permissions bit not used in DOS/Windows */ #define S_NOT_CONTENT_INDEXED 040 /* Reuse permissions bit not used in DOS/Windows */ #define S_OFFLINE 01000 /* Reuse sticky bit, not used in DOS/Windows */ #define S_SPARSE_FILE 02000 /* Reuse GID bit, not used in DOS/Windows */ #define S_MOUNT_POINT 04000 /* Reuse UID bit, not used in DOS/Windows */ /* #define S_TEMPORARY /* Reuse UID bit, not used in DOS/Windows */ /* #define S_VIRTUAL /* No bit left for this one */ #if defined(_MSDOS) #define _mkdirx(path, mode) _mkdir(path) #elif defined(_WIN32) #if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) #define _mkdirx(path, mode) mkdirU(path, mode) #else /* _ANSI_SOURCE */ #define _mkdirx(path, mode) mkdirA(path, mode) #endif /* defined(_UTF8_SOURCE) */ extern int mkdirU(const char *path, mode_t mode); extern int mkdirA(const char *path, mode_t mode); #endif /* defined(_MSDOS) */ #define mkdir(path, mode) _mkdirx(path, mode) /* Special values for futimens() and utimensat(). Must not be in [0...((10^9)-1)] */ #define UTIME_NOW 1000000001 #define UTIME_OMIT 1000000002 #ifdef __cplusplus } #endif #endif /* defined(_MSVCLIBX_STAT_H) */