-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmingw32_wrapper.c
executable file
·152 lines (131 loc) · 3.53 KB
/
mingw32_wrapper.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "mingw32_wrapper.h"
char *realpath(const char *path, char resolved_path[PATH_MAX])
{
char *return_path = 0;
if (path) //Else EINVAL
{
if (resolved_path)
{
return_path = resolved_path;
}
else
{
//Non standard extension that glibc uses
return_path = malloc(PATH_MAX);
}
if (return_path) //Else EINVAL
{
//This is a Win32 API function similar to what realpath() is supposed to do
size_t size = GetFullPathNameA(path, PATH_MAX, return_path, 0);
//GetFullPathNameA() returns a size larger than buffer if buffer is too small
if (size > PATH_MAX)
{
if (return_path != resolved_path) //Malloc'd buffer - Unstandard extension retry
{
size_t new_size;
free(return_path);
return_path = malloc(size);
if (return_path)
{
new_size = GetFullPathNameA(path, size, return_path, 0); //Try again
if (new_size > size) //If it's still too large, we have a problem, don't try again
{
free(return_path);
return_path = 0;
errno = ENAMETOOLONG;
}
else
{
size = new_size;
}
}
else
{
//I wasn't sure what to return here, but the standard does say to return EINVAL
//if resolved_path is null, and in this case we couldn't malloc large enough buffer
errno = EINVAL;
}
}
else //resolved_path buffer isn't big enough
{
return_path = 0;
errno = ENAMETOOLONG;
}
}
//GetFullPathNameA() returns 0 if some path resolve problem occured
if (!size)
{
if (return_path != resolved_path) //Malloc'd buffer
{
free(return_path);
}
return_path = 0;
//Convert MS errors into standard errors
switch (GetLastError())
{
case ERROR_FILE_NOT_FOUND:
errno = ENOENT;
break;
case ERROR_PATH_NOT_FOUND: case ERROR_INVALID_DRIVE:
errno = ENOTDIR;
break;
case ERROR_ACCESS_DENIED:
errno = EACCES;
break;
default: //Unknown Error
errno = EIO;
break;
}
}
//If we get to here with a valid return_path, we're still doing good
if (return_path)
{
struct stat stat_buffer;
//Make sure path exists, stat() returns 0 on success
if (stat(return_path, &stat_buffer))
{
if (return_path != resolved_path)
{
free(return_path);
}
return_path = 0;
//stat() will set the correct errno for us
}
//else we succeeded!
}
}
else
{
errno = EINVAL;
}
}
else
{
errno = EINVAL;
}
return return_path;
}
long getpagesize (void) {
static long g_pagesize = 0;
if (! g_pagesize) {
SYSTEM_INFO system_info;
GetSystemInfo (&system_info);
g_pagesize = system_info.dwPageSize;
}
return g_pagesize;
}
int pread(unsigned int fd, char *buf, size_t count, int offset)
{
if (_lseek(fd, offset, SEEK_SET) != offset) {
return -1;
}
return read(fd, buf, count);
}
int pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
{
long ret = _lseek(fd, offset, SEEK_SET);
if (ret == -1) {
return(-1);
}
return(_write(fd, buf, nbytes));
}