Skip to content

Commit 8510867

Browse files
committed
add C interfaces
1 parent 42c839c commit 8510867

File tree

1 file changed

+75
-2
lines changed

1 file changed

+75
-2
lines changed

src/stdlib_system.c

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,44 @@
1+
#include <stdbool.h>
12
#include <stddef.h>
23
#include <sys/stat.h>
34
#include <sys/types.h>
45
#include <string.h>
56
#include <errno.h>
67
#ifdef _WIN32
78
#include <direct.h>
9+
#include <windows.h>
810
#else
911
#include <unistd.h>
1012
#endif /* ifdef _WIN32 */
1113

12-
// Returns the string describing the meaning of `errno` code (by calling `strerror`).
13-
char* stdlib_strerror(size_t* len){
14+
// Wrapper to get the string describing a system syscall error.
15+
// Uses `strerr` on unix.
16+
// if `winapi` is `false`, uses the usual `strerr` on windows.
17+
// If `winapi` is `false`, uses `FormatMessage`(from windows.h) on windows.
18+
char* stdlib_strerror(size_t* len, bool winapi){
19+
20+
if (winapi) {
21+
#ifdef _WIN32
22+
LPSTR err = NULL;
23+
DWORD dw = GetLastError();
24+
25+
FormatMessage(
26+
FORMAT_MESSAGE_ALLOCATE_BUFFER |
27+
FORMAT_MESSAGE_FROM_SYSTEM |
28+
FORMAT_MESSAGE_IGNORE_INSERTS,
29+
NULL,
30+
dw,
31+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
32+
(LPSTR) &err,
33+
0,
34+
NULL);
35+
36+
*len = strlen(err);
37+
return (char*) err;
38+
39+
#endif /* ifdef _WIN32 */
40+
}
41+
1442
char* err = strerror(errno);
1543
*len = strlen(err);
1644
return err;
@@ -44,3 +72,48 @@ int stdlib_remove_directory(const char* path){
4472

4573
return (!code) ? 0 : errno;
4674
}
75+
76+
// Wrapper to the platform's `stat`(status of path) call.
77+
// Uses `lstat` on unix, `GetFileAttributesA` on windows.
78+
// Returns the `type` of the path, and sets the `stat`(if any errors).
79+
int stdlib_exists(const char* path, int* stat){
80+
// All the valid types
81+
const int type_unknown = 0;
82+
const int type_regular_file = 1;
83+
const int type_directory = 2;
84+
const int type_symlink = 3;
85+
86+
int type = type_unknown;
87+
*stat = 0;
88+
89+
#ifdef _WIN32
90+
DWORD attrs = GetFileAttributesA(path);
91+
92+
if (attrs == INVALID_FILE_ATTRIBUTES) {
93+
*stat = (int) GetLastError();
94+
return type_unknown;
95+
}
96+
97+
if (attrs & FILE_ATTRIBUTE_NORMAL) type = type_regular_file;
98+
if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) type = type_symlink;
99+
if (attrs & FILE_ATTRIBUTE_DIRECTORY) type = type_directory;
100+
#else
101+
struct stat buf = {0};
102+
int status;
103+
status = lstat(path, &buf);
104+
105+
if (status == -1) {
106+
// `lstat` failed
107+
*stat = errno;
108+
return type_unknown;
109+
}
110+
111+
switch (buf.st_mode & S_IFMT) {
112+
case S_IFREG: type = type_regular_file; break;
113+
case S_IFDIR: type = type_directory; break;
114+
case S_IFLNK: type = type_symlink; break;
115+
default: type = type_unknown; break;
116+
}
117+
#endif /* ifdef _WIN32 */
118+
return type;
119+
}

0 commit comments

Comments
 (0)