Skip to content

Commit 9827616

Browse files
author
onthfixe
committed
fix: define S_ISREG on Windows
- detect whether POSIX-style macros exist before using them - fall back to the MSVC _S_IF* constants when needed
1 parent 513ff50 commit 9827616

File tree

1 file changed

+71
-41
lines changed

1 file changed

+71
-41
lines changed

src/stdlib_system.c

Lines changed: 71 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99
#ifdef _WIN32
1010
#include <direct.h>
1111
#include <windows.h>
12+
#ifndef S_ISREG
13+
#if defined(S_IFMT) && defined(S_IFREG)
14+
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
15+
#elif defined(_S_IFMT) && defined(_S_IFREG)
16+
#define S_ISREG(mode) (((mode) & _S_IFMT) == _S_IFREG)
17+
#endif
18+
#endif /* ifndef S_ISREG */
1219
#else
1320
#include <unistd.h>
1421
#endif /* ifdef _WIN32 */
@@ -17,54 +24,58 @@
1724
// Always Uses `strerr` on unix.
1825
// if `winapi` is `false`, uses the usual `strerr` on windows.
1926
// If `winapi` is `true`, uses `FormatMessageA`(from windows.h) on windows.
20-
char* stdlib_strerror(size_t* len, bool winapi){
27+
char *stdlib_strerror(size_t *len, bool winapi)
28+
{
2129

22-
if (winapi) {
30+
if (winapi)
31+
{
2332
#ifdef _WIN32
24-
LPSTR err = NULL;
25-
DWORD dw = GetLastError();
26-
27-
FormatMessageA(
28-
FORMAT_MESSAGE_ALLOCATE_BUFFER |
29-
FORMAT_MESSAGE_FROM_SYSTEM |
30-
FORMAT_MESSAGE_IGNORE_INSERTS,
31-
NULL,
32-
dw,
33-
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
34-
(LPSTR) &err,
35-
0,
36-
NULL);
37-
38-
*len = strlen(err);
39-
return (char*) err;
33+
LPSTR err = NULL;
34+
DWORD dw = GetLastError();
35+
36+
FormatMessageA(
37+
FORMAT_MESSAGE_ALLOCATE_BUFFER |
38+
FORMAT_MESSAGE_FROM_SYSTEM |
39+
FORMAT_MESSAGE_IGNORE_INSERTS,
40+
NULL,
41+
dw,
42+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
43+
(LPSTR)&err,
44+
0,
45+
NULL);
46+
47+
*len = strlen(err);
48+
return (char *)err;
4049

4150
#endif /* ifdef _WIN32 */
4251
}
4352

44-
char* err = strerror(errno);
53+
char *err = strerror(errno);
4554
*len = strlen(err);
4655
return err;
4756
}
4857

4958
// Wrapper to the platform's `mkdir`(make directory) call.
5059
// Uses `mkdir` on unix, `_mkdir` on windows.
5160
// Returns 0 if successful, otherwise returns the `errno`.
52-
int stdlib_make_directory(const char* path){
61+
int stdlib_make_directory(const char *path)
62+
{
5363
int code;
5464
#ifdef _WIN32
5565
code = _mkdir(path);
5666
#else
5767
// Default mode 0777
5868
code = mkdir(path, 0777);
5969
#endif /* ifdef _WIN32 */
60-
70+
6171
return (!code) ? 0 : errno;
6272
}
6373

6474
// Wrapper to the platform's `rmdir`(remove directory) call.
6575
// Uses `rmdir` on unix, `_rmdir` on windows.
6676
// Returns 0 if successful, otherwise returns the `errno`.
67-
int stdlib_remove_directory(const char* path){
77+
int stdlib_remove_directory(const char *path)
78+
{
6879
int code;
6980
#ifdef _WIN32
7081
code = _rmdir(path);
@@ -77,13 +88,15 @@ int stdlib_remove_directory(const char* path){
7788
// Wrapper to the platform's `getcwd`(get current working directory) call.
7889
// Uses `getcwd` on unix, `_getcwd` on windows.
7990
// Returns the cwd, sets the length of cwd and the `stat` of the operation.
80-
char* stdlib_get_cwd(size_t* len, int* stat){
91+
char *stdlib_get_cwd(size_t *len, int *stat)
92+
{
8193
*stat = 0;
8294
#ifdef _WIN32
83-
char* buffer;
95+
char *buffer;
8496
buffer = _getcwd(NULL, 0);
8597

86-
if (buffer == NULL) {
98+
if (buffer == NULL)
99+
{
87100
*stat = errno;
88101
return NULL;
89102
}
@@ -92,13 +105,14 @@ char* stdlib_get_cwd(size_t* len, int* stat){
92105
return buffer;
93106
#else
94107
char buffer[PATH_MAX + 1];
95-
if (!getcwd(buffer, sizeof(buffer))) {
108+
if (!getcwd(buffer, sizeof(buffer)))
109+
{
96110
*stat = errno;
97111
}
98112

99113
*len = strlen(buffer);
100114

101-
char* res = malloc(*len);
115+
char *res = malloc(*len);
102116
strncpy(res, buffer, *len);
103117

104118
return res;
@@ -108,21 +122,23 @@ char* stdlib_get_cwd(size_t* len, int* stat){
108122
// Wrapper to the platform's `chdir`(change directory) call.
109123
// Uses `chdir` on unix, `_chdir` on windows.
110124
// Returns 0 if successful, otherwise returns the `errno`.
111-
int stdlib_set_cwd(char* path) {
125+
int stdlib_set_cwd(char *path)
126+
{
112127
int code;
113128
#ifdef _WIN32
114129
code = _chdir(path);
115130
#else
116131
code = chdir(path);
117132
#endif /* ifdef _WIN32 */
118-
133+
119134
return (code == -1) ? errno : 0;
120135
}
121136

122137
// Wrapper to the platform's `stat`(status of path) call.
123138
// Uses `lstat` on unix, `GetFileAttributesA` on windows.
124139
// Returns the `type` of the path, and sets the `stat`(if any errors).
125-
int stdlib_exists(const char* path, int* stat){
140+
int stdlib_exists(const char *path, int *stat)
141+
{
126142
// All the valid types
127143
const int fs_type_unknown = 0;
128144
const int fs_type_regular_file = 1;
@@ -135,40 +151,54 @@ int stdlib_exists(const char* path, int* stat){
135151
#ifdef _WIN32
136152
DWORD attrs = GetFileAttributesA(path);
137153

138-
if (attrs == INVALID_FILE_ATTRIBUTES) {
139-
*stat = (int) GetLastError();
154+
if (attrs == INVALID_FILE_ATTRIBUTES)
155+
{
156+
*stat = (int)GetLastError();
140157
return fs_type_unknown;
141158
}
142159

143160
// Let's assume it is a regular file
144161
type = fs_type_regular_file;
145162

146-
if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) type = fs_type_symlink;
147-
if (attrs & FILE_ATTRIBUTE_DIRECTORY) type = fs_type_directory;
163+
if (attrs & FILE_ATTRIBUTE_REPARSE_POINT)
164+
type = fs_type_symlink;
165+
if (attrs & FILE_ATTRIBUTE_DIRECTORY)
166+
type = fs_type_directory;
148167
#else
149168
struct stat buf = {0};
150169
int status;
151170
status = lstat(path, &buf);
152171

153-
if (status == -1) {
172+
if (status == -1)
173+
{
154174
// `lstat` failed
155175
*stat = errno;
156176
return fs_type_unknown;
157177
}
158178

159-
switch (buf.st_mode & S_IFMT) {
160-
case S_IFREG: type = fs_type_regular_file; break;
161-
case S_IFDIR: type = fs_type_directory; break;
162-
case S_IFLNK: type = fs_type_symlink; break;
163-
default: type = fs_type_unknown; break;
179+
switch (buf.st_mode & S_IFMT)
180+
{
181+
case S_IFREG:
182+
type = fs_type_regular_file;
183+
break;
184+
case S_IFDIR:
185+
type = fs_type_directory;
186+
break;
187+
case S_IFLNK:
188+
type = fs_type_symlink;
189+
break;
190+
default:
191+
type = fs_type_unknown;
192+
break;
164193
}
165194
#endif /* ifdef _WIN32 */
166195
return type;
167196
}
168197

169198
// `stat` and `_stat` follow symlinks automatically.
170199
// so no need for winapi functions.
171-
bool stdlib_is_file(const char* path) {
200+
bool stdlib_is_file(const char *path)
201+
{
172202
#ifdef _WIN32
173203
struct _stat buf = {0};
174204
return _stat(path, &buf) == 0 && S_ISREG(buf.st_mode);

0 commit comments

Comments
 (0)